didn't find out implicit bind implementation from connect call.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi all,

I am a newbies to linux kernel. I was browsing the kernel code for 
TCP/IP implementation.I was looking into the implementation of
"tcp_v4_connect" function.

lets consider the following situation.
client side implementation:
---------------------------
int sockfd;
struct sockaddr_in sin_addr;

sockfd = socket(AF_INET,SOCK_STREAM,0);
...
//sin_addr has been populated by remote ip and port and AF_INET family.
//client didn't explicitly bind local addr/port
...
ret = connect(sockfd,(struct sockaddr*)sin_addr,sizeof(struct sockaddr_in));
...

As most of the tcp/ip books discuss that the kernel will implicitly bind 
local port/ip before actually send the SYN packet.


While looking into the "tcp_v4_connect" implementation i didn't figure out
which portion of the code is responsible for implicit local/ip port binding.

Any pointer will help me to understand the TCP/IP stack implementation better.

Thanx and regards,
Samarjit

(N.B. Please copy the response to this personal email)

The tcp_v4_connect implementation is as follows.(for linux kernel 2.6.23 patch 2.6.23.1)
---------------------------------------------------------------
/* This will initiate an outgoing connection. */
int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
        struct inet_sock *inet = inet_sk(sk);
        struct tcp_sock *tp = tcp_sk(sk);
        struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
        struct rtable *rt;
        __be32 daddr, nexthop;
        int tmp;
        int err;

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

        if (usin->sin_family != AF_INET)
                return -EAFNOSUPPORT;

        nexthop = daddr = usin->sin_addr.s_addr;
        if (inet->opt && inet->opt->srr) {
                if (!daddr)
                        return -EINVAL;
                nexthop = inet->opt->faddr;
        }

        tmp = ip_route_connect(&rt, nexthop, inet->saddr,
                               RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
                               IPPROTO_TCP,
                               inet->sport, usin->sin_port, sk, 1);
        if (tmp < 0) {
                if (tmp == -ENETUNREACH)
                        IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
                return tmp;
         }

        if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
                ip_rt_put(rt);
                return -ENETUNREACH;
        }

        if (!inet->opt || !inet->opt->srr)
                daddr = rt->rt_dst;

        if (!inet->saddr)
                inet->saddr = rt->rt_src;
        inet->rcv_saddr = inet->saddr;

        if (tp->rx_opt.ts_recent_stamp && inet->daddr != daddr) {
                /* Reset inherited state */
                tp->rx_opt.ts_recent       = 0;
                tp->rx_opt.ts_recent_stamp = 0;
                tp->write_seq              = 0;
        }

        if (tcp_death_row.sysctl_tw_recycle &&
            !tp->rx_opt.ts_recent_stamp && rt->rt_dst == daddr) {
                struct inet_peer *peer = rt_get_peer(rt);
                /*
                 * VJ's idea. We save last timestamp seen from
                 * the destination in peer table, when entering state
                 * TIME-WAIT * and initialize rx_opt.ts_recent from it,
                 * when trying new connection.
                 */
                if (peer != NULL &&
                    peer->tcp_ts_stamp + TCP_PAWS_MSL >= get_seconds()) {
                        tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp;
                        tp->rx_opt.ts_recent = peer->tcp_ts;
                }
        }
        inet->dport = usin->sin_port;
        inet->daddr = daddr;

        inet_csk(sk)->icsk_ext_hdr_len = 0;
        if (inet->opt)
                inet_csk(sk)->icsk_ext_hdr_len = inet->opt->optlen;

        tp->rx_opt.mss_clamp = 536;

        /* Socket identity is still unknown (sport may be zero).
         * However we set state to SYN-SENT and not releasing socket
         * lock select source port, enter ourselves into the hash tables and
         * complete initialization after this.
         */
        tcp_set_state(sk, TCP_SYN_SENT);
        err = inet_hash_connect(&tcp_death_row, sk);
        if (err)
                goto failure;

        err = ip_route_newports(&rt, IPPROTO_TCP,
                                inet->sport, inet->dport, sk);
        if (err)
                goto failure;

        /* OK, now commit destination to socket.  */
        sk->sk_gso_type = SKB_GSO_TCPV4;
        sk_setup_caps(sk, &rt->u.dst);

        if (!tp->write_seq)
                tp->write_seq = secure_tcp_sequence_number(inet->saddr,
                                                           inet->daddr,
                                                           inet->sport,
                                                           usin->sin_port);

        inet->id = tp->write_seq ^ jiffies;

        err = tcp_connect(sk);
        rt = NULL;
        if (err)
                goto failure;

        return 0;

failure:
        /*
         * This unhashes the socket and releases the local port,
         * if necessary.
         */
        tcp_set_state(sk, TCP_CLOSE);
        ip_rt_put(rt);
        sk->sk_route_caps = 0;
        inet->dport = 0;
        return err;
}





      5, 50, 500, 5000 - Store N number of mails in your inbox. Go to http://help.yahoo.com/l/in/yahoo/mail/yahoomail/tools/tools-08.html
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux