static inline int tcp_ipv4_bind(FAR struct tcp_conn_s *conn, FAR const struct sockaddr_in *addr) { int port; int ret; /* Verify or select a local port and address */ net_lock(); /* Verify or select a local port (host byte order) */ #ifdef CONFIG_NETDEV_MULTINIC port = tcp_selectport(PF_INET, (FAR const union ip_addr_u *)&addr->sin_addr.s_addr, ntohs(addr->sin_port)); #else port = tcp_selectport(ntohs(addr->sin_port)); #endif if (port < 0) { nerr("ERROR: tcp_selectport failed: %d\n", port); return port; } /* Save the local address in the connection structure (network byte order). */ conn->lport = htons(port); #ifdef CONFIG_NETDEV_MULTINIC net_ipv4addr_copy(conn->u.ipv4.laddr, addr->sin_addr.s_addr); #endif /* Find the device that can receive packets on the network associated with * this local address. */ ret = tcp_local_ipv4_device(conn); if (ret < 0) { /* If no device is found, then the address is not reachable */ nerr("ERROR: tcp_local_ipv4_device failed: %d\n", ret); /* Back out the local address setting */ conn->lport = 0; #ifdef CONFIG_NETDEV_MULTINIC net_ipv4addr_copy(conn->u.ipv4.laddr, INADDR_ANY); #endif return ret; } net_unlock(); return OK; }
int tcp_bind(FAR struct tcp_conn_s *conn, FAR const struct sockaddr_in *addr) #endif { net_lock_t flags; int port; /* Verify or select a local port */ flags = net_lock(); port = tcp_selectport(ntohs(addr->sin_port)); net_unlock(flags); if (port < 0) { return port; } /* Save the local address in the connection structure. Note that the requested * local IP address is saved but not used. At present, only a single network * interface is supported, the IP address is not of importance. */ conn->lport = addr->sin_port; #if 0 /* Not used */ #ifdef CONFIG_NET_IPv6 net_ipaddr_copy(conn->lipaddr, addr->sin6_addr.in6_u.u6_addr16); #else net_ipaddr_copy(conn->lipaddr, addr->sin_addr.s_addr); #endif #endif return OK; }
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; }
static inline int tcp_ipv6_bind(FAR struct tcp_conn_s *conn, FAR const struct sockaddr_in6 *addr) { int port; int ret; /* Verify or select a local port and address */ net_lock(); /* Verify or select a local port (host byte order) */ #ifdef CONFIG_NETDEV_MULTINIC /* The port number must be unique for this address binding */ port = tcp_selectport(PF_INET6, (FAR const union ip_addr_u *)addr->sin6_addr.in6_u.u6_addr16, ntohs(addr->sin6_port)); #else /* There is only one network device; the port number can be globally * unique. */ port = tcp_selectport(ntohs(addr->sin6_port)); #endif if (port < 0) { nerr("ERROR: tcp_selectport failed: %d\n", port); return port; } /* Save the local address in the connection structure (network byte order). */ conn->lport = htons(port); #ifdef CONFIG_NETDEV_MULTINIC net_ipv6addr_copy(conn->u.ipv6.laddr, addr->sin6_addr.in6_u.u6_addr16); #endif /* Find the device that can receive packets on the network * associated with this local address. */ ret = tcp_local_ipv6_device(conn); if (ret < 0) { /* If no device is found, then the address is not reachable */ nerr("ERROR: tcp_local_ipv6_device failed: %d\n", ret); /* Back out the local address setting */ conn->lport = 0; #ifdef CONFIG_NETDEV_MULTINIC net_ipv6addr_copy(conn->u.ipv6.laddr, g_ipv6_allzeroaddr); #endif return ret; } net_unlock(); return OK; }
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; }