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; }
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; }
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; }
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; };