FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct tcp_iphdr_s *buf) { FAR struct tcp_conn_s *conn = tcp_alloc(); if (conn) { /* Fill in the necessary fields for the new connection. */ conn->rto = TCP_RTO; conn->timer = TCP_RTO; conn->sa = 0; conn->sv = 4; conn->nrtx = 0; conn->lport = buf->destport; conn->rport = buf->srcport; conn->mss = TCP_INITIAL_MSS; net_ipaddr_copy(conn->ripaddr, net_ip4addr_conv32(buf->srcipaddr)); conn->tcpstateflags = TCP_SYN_RCVD; tcp_initsequence(conn->sndseq); conn->unacked = 1; #ifdef CONFIG_NET_TCP_WRITE_BUFFERS conn->expired = 0; conn->isn = 0; conn->sent = 0; #endif /* rcvseq should be the seqno from the incoming packet + 1. */ memcpy(conn->rcvseq, buf->seqno, 4); #ifdef CONFIG_NET_TCP_READAHEAD /* Initialize the list of TCP read-ahead buffers */ IOB_QINIT(&conn->readahead); #endif #ifdef CONFIG_NET_TCP_WRITE_BUFFERS /* Initialize the write buffer lists */ sq_init(&conn->write_q); sq_init(&conn->unacked_q); #endif /* And, finally, put the connection structure into the active list. * Interrupts should already be disabled in this context. */ dq_addlast(&conn->node, &g_active_tcp_connections); } return conn; }
int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr_in *addr) #endif { net_lock_t flags; int port; /* The connection is expected to be in the TCP_ALLOCATED state.. i.e., * allocated via up_tcpalloc(), but not yet put into the active connections * list. */ if (!conn || conn->tcpstateflags != TCP_ALLOCATED) { return -EISCONN; } /* If the TCP port has not already been bound to a local port, then select * one now. */ flags = net_lock(); port = tcp_selectport(ntohs(conn->lport)); net_unlock(flags); if (port < 0) { return port; } /* Initialize and return the connection structure, bind it to the port number */ conn->tcpstateflags = TCP_SYN_SENT; tcp_initsequence(conn->sndseq); conn->mss = TCP_INITIAL_MSS; conn->unacked = 1; /* TCP length of the SYN is one. */ conn->nrtx = 0; conn->timer = 1; /* Send the SYN next time around. */ conn->rto = TCP_RTO; conn->sa = 0; conn->sv = 16; /* Initial value of the RTT variance. */ conn->lport = htons((uint16_t)port); #ifdef CONFIG_NET_TCP_WRITE_BUFFERS conn->expired = 0; conn->isn = 0; conn->sent = 0; #endif /* The sockaddr port is 16 bits and already in network order */ conn->rport = addr->sin_port; /* The sockaddr address is 32-bits in network order. */ net_ipaddr_copy(conn->ripaddr, addr->sin_addr.s_addr); #ifdef CONFIG_NET_TCP_READAHEAD /* Initialize the list of TCP read-ahead buffers */ IOB_QINIT(&conn->readahead); #endif #ifdef CONFIG_NET_TCP_WRITE_BUFFERS /* Initialize the TCP write buffer lists */ sq_init(&conn->write_q); sq_init(&conn->unacked_q); #endif /* And, finally, put the connection structure into the active * list. Because g_active_tcp_connections is accessed from user level and * interrupt level, code, it is necessary to keep interrupts disabled during * this operation. */ flags = net_lock(); dq_addlast(&conn->node, &g_active_tcp_connections); net_unlock(flags); return OK; }
FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev, FAR struct tcp_hdr_s *tcp) { FAR struct tcp_conn_s *conn; uint8_t domain; int ret; /* Get the appropriate IP domain */ #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv4) bool ipv6 = IFF_IS_IPv6(dev->d_flags); domain = ipv6 ? PF_INET6 : PF_INET; #elif defined(CONFIG_NET_IPv4) domain = PF_INET; #else /* defined(CONFIG_NET_IPv6) */ domain = PF_INET6; #endif /* Allocate the connection structure */ conn = tcp_alloc(domain); if (conn) { /* Set up the local address (laddr) and the remote address (raddr) * that describes the TCP connection. */ #ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv4 if (ipv6) #endif { FAR struct ipv6_hdr_s *ip = IPv6BUF; /* Set the IPv6 specific MSS and the IPv6 locally bound address */ conn->mss = TCP_IPv6_INITIAL_MSS(dev); net_ipv6addr_copy(conn->u.ipv6.raddr, ip->srcipaddr); #ifdef CONFIG_NETDEV_MULTINIC net_ipv6addr_copy(conn->u.ipv6.laddr, ip->destipaddr); /* We now have to filter all outgoing transfers so that they use * only the MSS of this device. */ DEBUGASSERT(conn->dev == NULL || conn->dev == dev); conn->dev = dev; #endif /* Find the device that can receive packets on the network * associated with this local address. */ ret = tcp_remote_ipv6_device(conn); } #endif /* CONFIG_NET_IPv6 */ #ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv6 else #endif { FAR struct ipv4_hdr_s *ip = IPv4BUF; /* Set the IPv6 specific MSS and the IPv4 bound remote address. */ conn->mss = TCP_IPv4_INITIAL_MSS(dev); net_ipv4addr_copy(conn->u.ipv4.raddr, net_ip4addr_conv32(ip->srcipaddr)); #ifdef CONFIG_NETDEV_MULTINIC /* Set the local address as well */ net_ipv4addr_copy(conn->u.ipv4.laddr, net_ip4addr_conv32(ip->destipaddr)); /* We now have to filter all outgoing transfers so that they use * only the MSS of this device. */ DEBUGASSERT(conn->dev == NULL || conn->dev == dev); conn->dev = dev; #endif /* Find the device that can receive packets on the network * associated with this local address. */ ret = tcp_remote_ipv4_device(conn); } #endif /* CONFIG_NET_IPv4 */ /* Verify that a network device that can provide packets to this * local address was found. */ if (ret < 0) { /* If no device is found, then the address is not reachable. * That should be impossible in this context and we should * probably really just assert here. */ nerr("ERROR: Failed to find network device: %d\n", ret); tcp_free(conn); return NULL; } /* Fill in the necessary fields for the new connection. */ conn->rto = TCP_RTO; conn->timer = TCP_RTO; conn->sa = 0; conn->sv = 4; conn->nrtx = 0; conn->lport = tcp->destport; conn->rport = tcp->srcport; conn->tcpstateflags = TCP_SYN_RCVD; tcp_initsequence(conn->sndseq); conn->unacked = 1; #ifdef CONFIG_NET_TCP_WRITE_BUFFERS conn->expired = 0; conn->isn = 0; conn->sent = 0; conn->sndseq_max = 0; #endif /* rcvseq should be the seqno from the incoming packet + 1. */ memcpy(conn->rcvseq, tcp->seqno, 4); #ifdef CONFIG_NET_TCP_READAHEAD /* Initialize the list of TCP read-ahead buffers */ IOB_QINIT(&conn->readahead); #endif #ifdef CONFIG_NET_TCP_WRITE_BUFFERS /* Initialize the write buffer lists */ sq_init(&conn->write_q); sq_init(&conn->unacked_q); #endif /* And, finally, put the connection structure into the active list. * Interrupts should already be disabled in this context. */ dq_addlast(&conn->node, &g_active_tcp_connections); } return conn; }
int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr) { int port; int ret; /* The connection is expected to be in the TCP_ALLOCATED state.. i.e., * allocated via up_tcpalloc(), but not yet put into the active connections * list. */ if (!conn || conn->tcpstateflags != TCP_ALLOCATED) { return -EISCONN; } /* If the TCP port has not already been bound to a local port, then select * one now. We assume that the IP address has been bound to a local device, * but the port may still be INPORT_ANY. */ net_lock(); #ifdef CONFIG_NETDEV_MULTINIC /* If there are multiple network devices, then we need to pass the local, * bound address. This is needed because port unique-ness is only for a * given network. * * This is complicated by the fact that the local address may be either an * IPv4 or an IPv6 address. */ #ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv6 if (conn->domain == PF_INET) #endif { /* Select a port that is unique for this IPv4 local address (host * order). */ port = tcp_selectport(PF_INET, (FAR const union ip_addr_u *)&conn->u.ipv4.laddr, ntohs(conn->lport)); } #endif /* CONFIG_NET_IPv4 */ #ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv4 else #endif { /* Select a port that is unique for this IPv6 local address (host * order). */ port = tcp_selectport(PF_INET6, (FAR const union ip_addr_u *)conn->u.ipv6.laddr, ntohs(conn->lport)); } #endif /* CONFIG_NET_IPv6 */ #else /* CONFIG_NETDEV_MULTINIC */ /* Select the next available port number. This is only one network device * so we do not have to bother with all of the IPv4/IPv6 local address * silliness. */ port = tcp_selectport(ntohs(conn->lport)); #endif /* CONFIG_NETDEV_MULTINIC */ /* Did we have a port assignment? */ if (port < 0) { ret = port; goto errout_with_lock; } /* Set up the local address (laddr) and the remote address (raddr) that * describes the TCP connection. */ #ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv6 if (conn->domain == PF_INET) #endif { FAR const struct sockaddr_in *inaddr = (FAR const struct sockaddr_in *)addr; /* Save MSS and the port from the sockaddr (already in network order) */ conn->mss = MIN_IPv4_TCP_INITIAL_MSS; conn->rport = inaddr->sin_port; /* The sockaddr address is 32-bits in network order. */ net_ipv4addr_copy(conn->u.ipv4.raddr, inaddr->sin_addr.s_addr); /* Find the device that can receive packets on the network associated * with this remote address. */ ret = tcp_remote_ipv4_device(conn); } #endif /* CONFIG_NET_IPv4 */ #ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv4 else #endif { FAR const struct sockaddr_in6 *inaddr = (FAR const struct sockaddr_in6 *)addr; /* Save MSS and the port from the sockaddr (already in network order) */ conn->mss = MIN_IPv6_TCP_INITIAL_MSS; conn->rport = inaddr->sin6_port; /* The sockaddr address is 128-bits in network order. */ net_ipv6addr_copy(conn->u.ipv6.raddr, inaddr->sin6_addr.s6_addr16); /* Find the device that can receive packets on the network associated * with this local address. */ ret = tcp_remote_ipv6_device(conn); } #endif /* CONFIG_NET_IPv6 */ /* Verify that a network device that can provide packets to this local * address was found. */ if (ret < 0) { /* If no device is found, then the address is not reachable. That * should be impossible in this context and we should probably really * just assert here. */ nerr("ERROR: Failed to find network device: %d\n", ret); goto errout_with_lock; } /* Initialize and return the connection structure, bind it to the port * number. At this point, we do not know the size of the initial MSS We * know the total size of the packet buffer, but we don't yet know the * size of link layer header. */ conn->tcpstateflags = TCP_SYN_SENT; tcp_initsequence(conn->sndseq); conn->unacked = 1; /* TCP length of the SYN is one. */ conn->nrtx = 0; conn->timer = 1; /* Send the SYN next time around. */ conn->rto = TCP_RTO; conn->sa = 0; conn->sv = 16; /* Initial value of the RTT variance. */ conn->lport = htons((uint16_t)port); #ifdef CONFIG_NET_TCP_WRITE_BUFFERS conn->expired = 0; conn->isn = 0; conn->sent = 0; conn->sndseq_max = 0; #endif #ifdef CONFIG_NET_TCP_READAHEAD /* Initialize the list of TCP read-ahead buffers */ IOB_QINIT(&conn->readahead); #endif #ifdef CONFIG_NET_TCP_WRITE_BUFFERS /* Initialize the TCP write buffer lists */ sq_init(&conn->write_q); sq_init(&conn->unacked_q); #endif /* And, finally, put the connection structure into the active list. */ dq_addlast(&conn->node, &g_active_tcp_connections); ret = OK; errout_with_lock: net_unlock(); return ret; }