struct telnet_svc * telnet_svc_init(int port) { struct telnet_svc * tn = &telnet_svc; int th; if (port == 0) port = 23; /* use default TELNET srvice port */ tn->svc = tcp_alloc(); tn->tp = NULL; tcp_bind(tn->svc, INADDR_ANY, htons(port)); if (tcp_listen(tn->svc, 1) != 0) { INF("Can't register the TCP listner!"); return NULL; } tn->rx.nonempty_flag = thinkos_flag_alloc(); tn->rx.nonfull_flag = thinkos_flag_alloc(); tn->rx.head = 0; tn->rx.tail = 0; th = thinkos_thread_create_inf((void *)telnet_input_task, (void *)tn, &telnet_srv_inf); (void)th; INF("TELNET TCP input thread=%d", th); return tn; }
/* * Create socket and start connection to another host. * ! not wait until connection established. * \return socket in connection state * \return = NULL, or SExxx - some error */ tcp_socket_t *tcp_connect_start (ip_t *ip, ip_addr ipaddr, unsigned short port) { tcp_socket_t *s; tcp_debug ("tcp_connect to port %u\n", port); if (ipaddr.val == 0) return 0; mutex_lock (&ip->lock); s = tcp_alloc (ip); if (s == 0){ mutex_unlock (&ip->lock); return 0; } s->remote_ip.val = ipaddr.val; s->remote_port = port; if (s->local_port == 0) { s->local_port = tcp_new_port (ip); } mutex_unlock (&ip->lock); tcp_socket_t* res = tcp_connect_restart(s); if (SEANYERROR(res)){ mem_free(s); } return res; }
/* * Set the state of the connection to be LISTEN, which means that it * is able to accept incoming connections. The protocol control block * is reallocated in order to consume less memory. Setting the * connection to LISTEN is an irreversible process. */ tcp_socket_t *tcp_listen (ip_t *ip, unsigned char *ipaddr, unsigned short port) { tcp_socket_t *s, *cs; ip_addr targetip; if (ipaddr) { targetip = ipadr_4ucs(ipaddr); } else targetip.val = 0; s = tcp_alloc (ip); if (s == 0) { return 0; } /* Bind the connection to a local portnumber and IP address. */ mutex_lock (&ip->lock); if (port == 0) { port = tcp_new_port (ip); } tcp_debug ("tcp_listen: port %u\n", port); /* Check if the address already is in use. */ for (cs = ip->tcp_listen_sockets; cs != 0; cs = cs->next) { if (cs->local_port == port) { if ( ipadr_is_same(targetip.var, cs->local_ip) ) { mutex_unlock (&ip->lock); mem_free (s); return 0; } } } for (cs = ip->tcp_sockets; cs != 0; cs = cs->next) { if (cs->local_port == port) { if (ipadr_is_same(targetip.var, cs->local_ip) ) { mutex_unlock (&ip->lock); mem_free (s); return 0; } } } if ( ipadr_not0(targetip.var) ) { s->local_ip = targetip.var; } s->local_port = port; s->state = LISTEN; buf_queueh_init(&s->inq, sizeof(s->queue)); tcp_list_add (&ip->tcp_listen_sockets, s); mutex_unlock (&ip->lock); return s; }
/* * Connect to another host. Wait until connection established. * Return 1 on success, 0 on error. */ tcp_socket_t * tcp_connect (ip_t *ip, unsigned char *ipaddr, unsigned short port) { tcp_socket_t *s; unsigned long optdata; tcp_debug ("tcp_connect to port %u\n", port); if (ipaddr == 0) return 0; mutex_lock (&ip->lock); s = tcp_alloc (ip); memcpy (s->remote_ip, ipaddr, 4); s->remote_port = port; if (s->local_port == 0) { s->local_port = tcp_new_port (ip); } s->lastack = s->snd_nxt - 1; s->snd_lbb = s->snd_nxt - 1; s->snd_wnd = TCP_WND; s->ssthresh = s->mss * 10; s->state = SYN_SENT; /* Build an MSS option */ optdata = HTONL (((unsigned long)2 << 24) | ((unsigned long)4 << 16) | (((unsigned long)s->mss / 256) << 8) | (s->mss & 255)); if (! tcp_enqueue (s, 0, 0, TCP_SYN, (unsigned char*) &optdata, 4)) { mem_free (s); mutex_unlock (&ip->lock); return 0; } tcp_list_add (&ip->tcp_sockets, s); tcp_output (s); mutex_unlock (&ip->lock); mutex_lock (&s->lock); for (;;) { mutex_wait (&s->lock); if (s->state == ESTABLISHED) { mutex_unlock (&s->lock); return s; } if (s->state == CLOSED) { mutex_unlock (&s->lock); mem_free (s); return 0; } } }
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; }
static int psock_tcp_alloc(FAR struct socket *psock) { /* Allocate the TCP connection structure */ FAR struct tcp_conn_s *conn = tcp_alloc(psock->s_domain); if (!conn) { /* Failed to reserve a connection structure */ return -ENOMEM; } /* Set the reference count on the connection structure. This reference * count will be incremented only if the socket is dup'ed */ DEBUGASSERT(conn->crefs == 0); conn->crefs = 1; /* Save the pre-allocated connection in the socket structure */ psock->s_conn = conn; return OK; }
int __attribute__((noreturn)) dcc_tcp_read_task(armice_ctrl_t * ctrl, int id) { struct dcc_tcp_parm tcp_parm; jtag_arm_dcc_t * arm_dcc = &ctrl->arm_dcc; uint32_t buf[DCC_TCP_BUF_SIZE / sizeof(uint32_t)]; struct tcp_pcb * tp; struct tcp_pcb * mux; int th; int n; int port = 1001; for (;;) { mux = tcp_alloc(); DCC_LOG1(LOG_TRACE, "mux=%p", mux); tcp_bind(mux, INADDR_ANY, htons(port)); if (tcp_listen(mux, 1) != 0) { DCC_LOG1(LOG_WARNING, "<%d> tcp_listen()", id); break; } if ((tp = tcp_accept(mux)) == NULL) { DCC_LOG(LOG_ERROR, "tcp_accept()."); break; } tcp_close(mux); DCC_LOG2(LOG_TRACE, "%I:%d accepted.", tp->t_faddr, ntohs(tp->t_fport)); jtag_arm_dcc_open(arm_dcc); tcp_parm.tp = tp; tcp_parm.arm_dcc = arm_dcc; th = uthread_create(dcc_write_stack, sizeof(dcc_write_stack), (uthread_task_t)dcc_tcp_write_task, (void *)&tcp_parm, 0, NULL); if (th < 0) { DCC_LOG(LOG_ERROR, "uthread_create() fail!"); jtag_arm_dcc_close(arm_dcc); tcp_close(tp); DCC_LOG2(LOG_TRACE, "%I:%d closed.", tp->t_faddr, ntohs(tp->t_fport)); break; } for (;;) { if ((n = jtag_arm_dcc_read(arm_dcc, buf, sizeof(buf), 500)) < 0) { DCC_LOG1(LOG_WARNING, "jtag_arm_dcc_read(): %d", n); break; } DCC_LOG1(LOG_MSG, "jtag_arm_dcc_read(): %d", n); if (n == 0) { continue; } if ((n = tcp_send(tp, buf, n, 0)) < 0) { DCC_LOG2(LOG_TRACE, "%I:%d error.", tp->t_faddr, ntohs(tp->t_fport)); break; } } jtag_arm_dcc_close(arm_dcc); DCC_LOG2(LOG_TRACE, "%I:%d closed.", tp->t_faddr, ntohs(tp->t_fport)); tcp_close(tp); uthread_join(th); } for(;;); }
int rtsp_connect(struct rtsp_client * rtsp, const char * host, unsigned int port, const char * mrl) { struct tcp_pcb * tp; in_addr_t host_addr; if (!inet_aton(host, (struct in_addr *)&host_addr)) { return -1; } if ((tp = tcp_alloc()) == NULL) { ERR("can't allocate socket!"); return -1; } if (port == 0) { port = rtsp->port; if (port == 0) port = 554; } INF("RTSP://%s:%d/%s", host, port, mrl); if (tcp_connect(tp, host_addr, htons(port)) < 0) { ERR("can't connect to host!"); tcp_close(tp); return -1; } rtsp->tcp = tp; rtsp->port = port; rtsp->host_addr = host_addr; rtsp->rtp.faddr = host_addr; rtsp->cseq = 1; strcpy(rtsp->host_name, host); strcpy(rtsp->media_name, mrl); if (rtsp_request_options(rtsp) < 0) { ERR("rtsp_request_options() failed!"); return -1; } if (rtsp_request_describe(rtsp) < 0) { ERR("rtsp_request_describe() failed!"); return -1; } if (rtsp_sdp_decode(rtsp) < 0) { ERR("rtsp_sdp_decode() failed!"); return -1; } INF("Track:\"%s\"", rtsp->track_name); if (rtsp_request_setup(rtsp) < 0) { ERR("rtsp_request_setup() failed!"); return -1; } if (rtsp_request_play(rtsp) < 0) { ERR("rtsp_request_play() failed!"); return -1; } return 0; }
tcp_socket_t *tcp_accept_until (tcp_socket_t *s , scheduless_condition waitfor, void* waitarg) { tcp_socket_t *ns; buf_t *p; ip_hdr_t *iph; tcp_hdr_t *h; unsigned long optdata; int ok = tcp_lock_avail(s, (1<<LISTEN) , waitfor, waitarg); if (ok != 0){ if (s->state != LISTEN){ tcp_debug ("tcp_accept: called in invalid state\n"); return (tcp_socket_t *)SEINVAL; } if (ok == -1) return 0; return (tcp_socket_t *)ok; } /* Create a new PCB, and respond with a SYN|ACK. * If a new PCB could not be created (probably due to lack of memory), * we don't do anything, but rely on the sender will retransmit * the SYN at a time when we have more memory available. */ mutex_lock (&s->ip->lock); ns = tcp_alloc (s->ip); if (ns == 0) { mutex_unlock (&s->lock); ++(s->ip->tcp_in_discards); mutex_unlock (&s->ip->lock); tcp_debug ("tcp_accept: could not allocate PCB\n"); return (tcp_socket_t *)SENOMEM; } p = tcp_queue_get (s); h = (tcp_hdr_t*) p->payload; iph = ((ip_hdr_t*) p->payload) - 1; /* Set up the new PCB. */ ns->local_ip = iph->dest.var; ns->local_port = s->local_port; ns->remote_ip = iph->src; ns->remote_port = h->src; ns->state = SYN_RCVD; ns->rcv_nxt = s->ip->tcp_input_seqno + 1; ns->snd_wnd = h->wnd; ns->ssthresh = ns->snd_wnd; ns->snd_wl1 = s->ip->tcp_input_seqno; ns->ip = s->ip; mutex_unlock (&s->lock); /* Register the new PCB so that we can begin receiving * segments for it. */ tcp_list_add (&s->ip->tcp_sockets, ns); /* Parse any options in the SYN. */ tcp_parseopt (ns, h); /* Build an MSS option. */ optdata = HTONL (((unsigned long)2 << 24) | ((unsigned long)4 << 16) | (((unsigned long)ns->mss / 256) << 8) | (ns->mss & 255)); buf_free (p); /* Send a SYN|ACK together with the MSS option. * there is impossible fail of tcp_enqueue_option4 * */ tcp_enqueue_option4 (ns, TCP_SYN | TCP_ACK, optdata); #if TCP_LOCK_STYLE <= TCP_LOCK_SURE tcp_output (ns); mutex_unlock (&ns->ip->lock); #elif TCP_LOCK_STYLE >= TCP_LOCK_RELAXED mutex_unlock (&ns->ip->lock); tcp_output (ns); #endif mutex_unlock (&ns->lock); return ns; }
/** * Called by tcp_input() when a segment arrives for a listening * connection (from tcp_input()). * * @param pcb the tcp_pcb_listen for which a segment arrived * @return ERR_OK if the segment was processed * another err_t on error * * @note the return value is not (yet?) used in tcp_input() * @note the segment which arrived is saved in global variables, therefore only the pcb * involved is passed as a parameter to this function */ static err_t tcp_listen_input(struct tcp_pcb_listen *pcb) { struct tcp_pcb *npcb; u32_t optdata; /* In the LISTEN state, we check for incoming SYN segments, creates a new PCB, and responds with a SYN|ACK. */ if (flags & TCP_ACK) { /* For incoming segments with the ACK flag set, respond with a RST. */ LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n")); tcp_rst(ackno + 1, seqno + tcplen, &(iphdr->dest), &(iphdr->src), tcphdr->dest, tcphdr->src); } else if (flags & TCP_SYN) { LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest)); #if TCP_LISTEN_BACKLOG if (pcb->accepts_pending >= pcb->backlog) { return ERR_ABRT; } #endif /* TCP_LISTEN_BACKLOG */ npcb = tcp_alloc(pcb->prio); /* If a new PCB could not be created (probably due to lack of memory), we don't do anything, but rely on the sender will retransmit the SYN at a time when we have more memory available. */ if (npcb == NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n")); TCP_STATS_INC(tcp.memerr); return ERR_MEM; } #if TCP_LISTEN_BACKLOG pcb->accepts_pending++; #endif /* TCP_LISTEN_BACKLOG */ /* Set up the new PCB. */ ip_addr_set(&(npcb->local_ip), &(iphdr->dest)); npcb->local_port = pcb->local_port; ip_addr_set(&(npcb->remote_ip), &(iphdr->src)); npcb->remote_port = tcphdr->src; npcb->state = SYN_RCVD; npcb->rcv_nxt = seqno + 1; npcb->snd_wnd = tcphdr->wnd; npcb->ssthresh = npcb->snd_wnd; npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */ npcb->callback_arg = pcb->callback_arg; #if LWIP_CALLBACK_API npcb->accept = pcb->accept; #endif /* LWIP_CALLBACK_API */ /* inherit socket options */ npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER); /* Register the new PCB so that we can begin receiving segments for it. */ TCP_REG(&tcp_active_pcbs, npcb); /* Parse any options in the SYN. */ tcp_parseopt(npcb); #if TCP_CALCULATE_EFF_SEND_MSS npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip)); #endif /* TCP_CALCULATE_EFF_SEND_MSS */ snmp_inc_tcppassiveopens(); /* Build an MSS option. */ optdata = TCP_BUILD_MSS_OPTION(); /* Send a SYN|ACK together with the MSS option. */ tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, (u8_t *)&optdata, 4); return tcp_output(npcb); } return ERR_OK; }
tcp_socket_t * tcp_accept (tcp_socket_t *s) { tcp_socket_t *ns; buf_t *p; ip_hdr_t *iph; tcp_hdr_t *h; unsigned long optdata; again: mutex_lock (&s->lock); for (;;) { if (s->state != LISTEN) { mutex_unlock (&s->lock); tcp_debug ("tcp_accept: called in invalid state\n"); return 0; } if (! tcp_queue_is_empty (s)) { p = tcp_queue_get (s); break; } mutex_wait (&s->lock); } mutex_unlock (&s->lock); /* Create a new PCB, and respond with a SYN|ACK. * If a new PCB could not be created (probably due to lack of memory), * we don't do anything, but rely on the sender will retransmit * the SYN at a time when we have more memory available. */ mutex_lock (&s->ip->lock); ns = tcp_alloc (s->ip); if (ns == 0) { tcp_debug ("tcp_accept: could not allocate PCB\n"); ++s->ip->tcp_in_discards; mutex_unlock (&s->ip->lock); buf_free (p); goto again; } h = (tcp_hdr_t*) p->payload; iph = ((ip_hdr_t*) p->payload) - 1; /* Set up the new PCB. */ memcpy (ns->local_ip, iph->dest, 4); ns->local_port = s->local_port; memcpy (ns->remote_ip, iph->src, 4); ns->remote_port = h->src; ns->state = SYN_RCVD; ns->rcv_nxt = s->ip->tcp_input_seqno + 1; ns->snd_wnd = h->wnd; ns->ssthresh = ns->snd_wnd; ns->snd_wl1 = s->ip->tcp_input_seqno; ns->ip = s->ip; /* Register the new PCB so that we can begin receiving * segments for it. */ tcp_list_add (&s->ip->tcp_sockets, ns); /* Parse any options in the SYN. */ tcp_parseopt (ns, h); /* Build an MSS option. */ optdata = HTONL (((unsigned long)2 << 24) | ((unsigned long)4 << 16) | (((unsigned long)ns->mss / 256) << 8) | (ns->mss & 255)); buf_free (p); /* Send a SYN|ACK together with the MSS option. */ tcp_enqueue (ns, 0, 0, TCP_SYN | TCP_ACK, (unsigned char*) &optdata, 4); tcp_output (ns); mutex_unlock (&s->ip->lock); return ns; }
int psock_socket(int domain, int type, int protocol, FAR struct socket *psock) { int err; /* Only PF_INET, PF_INET6 or PF_PACKET domains supported */ if ( #if defined(CONFIG_NET_IPv6) domain != PF_INET6 #else domain != PF_INET #endif #if defined(CONFIG_NET_PKT) && domain != PF_PACKET #endif ) { err = EAFNOSUPPORT; goto errout; } /* Only SOCK_STREAM, SOCK_DGRAM and possible SOCK_RAW are supported */ if ( #if defined(CONFIG_NET_TCP) (type == SOCK_STREAM && protocol != 0 && protocol != IPPROTO_TCP) || #endif #if defined(CONFIG_NET_UDP) (type == SOCK_DGRAM && protocol != 0 && protocol != IPPROTO_UDP) || #endif ( #if defined(CONFIG_NET_TCP) #if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_PKT) type != SOCK_STREAM && #else type != SOCK_STREAM #endif #endif #if defined(CONFIG_NET_UDP) #if defined(CONFIG_NET_PKT) type != SOCK_DGRAM && #else type != SOCK_DGRAM #endif #endif #if defined(CONFIG_NET_PKT) type != SOCK_RAW #endif ) ) { err = EPROTONOSUPPORT; goto errout; } /* Everything looks good. Initialize the socket structure */ /* Save the protocol type */ psock->s_type = type; psock->s_conn = NULL; #ifdef CONFIG_NET_TCP_WRITE_BUFFERS psock->s_sndcb = NULL; #endif /* Allocate the appropriate connection structure. This reserves the * the connection structure is is unallocated at this point. It will * not actually be initialized until the socket is connected. */ err = ENOMEM; /* Assume failure to allocate connection instance */ switch (type) { #ifdef CONFIG_NET_PKT case SOCK_RAW: { /* Allocate the packet socket connection structure and save * in the new socket instance. */ FAR struct pkt_conn_s *conn = pkt_alloc(); if (!conn) { /* Failed to reserve a connection structure */ goto errout; } /* Set the reference count on the connection structure. This * reference count will be increment only if the socket is * dup'ed */ DEBUGASSERT(conn->crefs == 0); psock->s_conn = conn; conn->crefs = 1; } break; #endif #ifdef CONFIG_NET_TCP case SOCK_STREAM: { /* Allocate the TCP connection structure and save in the new * socket instance. */ FAR struct tcp_conn_s *conn = tcp_alloc(); if (!conn) { /* Failed to reserve a connection structure */ goto errout; /* With err == ENFILE or ENOMEM */ } /* Set the reference count on the connection structure. This * reference count will be increment only if the socket is * dup'ed */ DEBUGASSERT(conn->crefs == 0); psock->s_conn = conn; conn->crefs = 1; } break; #endif #ifdef CONFIG_NET_UDP case SOCK_DGRAM: { /* Allocate the UDP connection structure and save in the new * socket instance. */ FAR struct udp_conn_s *conn = udp_alloc(); if (!conn) { /* Failed to reserve a connection structure */ goto errout; /* With err == ENFILE or ENOMEM */ } /* Set the reference count on the connection structure. This * reference count will be increment only if the socket is * dup'ed */ DEBUGASSERT(conn->crefs == 0); psock->s_conn = conn; conn->crefs = 1; } break; #endif default: break; } return OK; errout: set_errno(err); return ERROR; }
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; }