Skip to content

Commit 2b17749

Browse files
mkshevetskiytrini
authored andcommitted
net/tcp: add connection info to tcp_stream structure
Changes: * Avoid use net_server_ip in tcp code, use tcp_stream data instead * Ignore packets from other connections if connection already created. This prevents us from connection break caused by other tcp stream. Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu> Reviewed-by: Simon Glass <sjg@chromium.org>
1 parent ddedfe1 commit 2b17749

File tree

6 files changed

+203
-102
lines changed

6 files changed

+203
-102
lines changed

include/net-legacy.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport,
416416
/**
417417
* net_send_tcp_packet() - Transmit TCP packet.
418418
* @payload_len: length of payload
419+
* @dhost: Destination host
419420
* @dport: Destination TCP port
420421
* @sport: Source TCP port
421422
* @action: TCP action to be performed
@@ -424,8 +425,8 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport,
424425
*
425426
* Return: 0 on success, other value on failure
426427
*/
427-
int net_send_tcp_packet(int payload_len, int dport, int sport, u8 action,
428-
u32 tcp_seq_num, u32 tcp_ack_num);
428+
int net_send_tcp_packet(int payload_len, struct in_addr dhost, int dport,
429+
int sport, u8 action, u32 tcp_seq_num, u32 tcp_ack_num);
429430
int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport,
430431
int sport, int payload_len);
431432

include/net/tcp.h

+50-7
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,9 @@ enum tcp_state {
279279

280280
/**
281281
* struct tcp_stream - TCP data stream structure
282+
* @rhost: Remote host, network byte order
283+
* @rport: Remote port, host byte order
284+
* @lport: Local port, host byte order
282285
*
283286
* @state: TCP connection state
284287
*
@@ -291,6 +294,10 @@ enum tcp_state {
291294
* @lost: Used for SACK
292295
*/
293296
struct tcp_stream {
297+
struct in_addr rhost;
298+
u16 rport;
299+
u16 lport;
300+
294301
/* TCP connection state */
295302
enum tcp_state state;
296303

@@ -305,16 +312,53 @@ struct tcp_stream {
305312
struct tcp_sack_v lost;
306313
};
307314

308-
struct tcp_stream *tcp_stream_get(void);
315+
void tcp_init(void);
316+
317+
typedef int tcp_incoming_filter(struct in_addr rhost,
318+
u16 rport, u16 sport);
319+
320+
/*
321+
* This function sets user callback used to accept/drop incoming
322+
* connections. Callback should:
323+
* + Check TCP stream endpoint and make connection verdict
324+
* - return non-zero value to accept connection
325+
* - return zero to drop connection
326+
*
327+
* WARNING: If callback is NOT defined, all incoming connections
328+
* will be dropped.
329+
*/
330+
void tcp_set_incoming_filter(tcp_incoming_filter *filter);
331+
332+
/*
333+
* tcp_stream_get -- Get or create TCP stream
334+
* @is_new: if non-zero and no stream found, then create a new one
335+
* @rhost: Remote host, network byte order
336+
* @rport: Remote port, host byte order
337+
* @lport: Local port, host byte order
338+
*
339+
* Returns: TCP stream structure or NULL (if not found/created)
340+
*/
341+
struct tcp_stream *tcp_stream_get(int is_new, struct in_addr rhost,
342+
u16 rport, u16 lport);
343+
344+
/*
345+
* tcp_stream_connect -- Create new TCP stream for remote connection.
346+
* @rhost: Remote host, network byte order
347+
* @rport: Remote port, host byte order
348+
*
349+
* Returns: TCP new stream structure or NULL (if not created).
350+
* Random local port will be used.
351+
*/
352+
struct tcp_stream *tcp_stream_connect(struct in_addr rhost, u16 rport);
353+
354+
enum tcp_state tcp_stream_get_state(struct tcp_stream *tcp);
309355

310-
enum tcp_state tcp_get_tcp_state(struct tcp_stream *tcp);
311-
void tcp_set_tcp_state(struct tcp_stream *tcp, enum tcp_state new_state);
312-
int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport,
313-
int sport, int payload_len,
356+
int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int payload_len,
314357
u8 action, u32 tcp_seq_num, u32 tcp_ack_num);
315358

316359
/**
317360
* rxhand_tcp() - An incoming packet handler.
361+
* @tcp: TCP stream
318362
* @pkt: pointer to the application packet
319363
* @dport: destination TCP port
320364
* @sip: source IP address
@@ -324,8 +368,7 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport,
324368
* @action: TCP action (SYN, ACK, FIN, etc)
325369
* @len: packet length
326370
*/
327-
typedef void rxhand_tcp(uchar *pkt, u16 dport,
328-
struct in_addr sip, u16 sport,
371+
typedef void rxhand_tcp(struct tcp_stream *tcp, uchar *pkt,
329372
u32 tcp_seq_num, u32 tcp_ack_num,
330373
u8 action, unsigned int len);
331374
void tcp_set_tcp_handler(rxhand_tcp *f);

net/fastboot_tcp.c

+27-23
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
#include <net/fastboot_tcp.h>
99
#include <net/tcp.h>
1010

11-
static char command[FASTBOOT_COMMAND_LEN] = {0};
12-
static char response[FASTBOOT_RESPONSE_LEN] = {0};
11+
#define FASTBOOT_TCP_PORT 5554
12+
13+
static char command[FASTBOOT_COMMAND_LEN];
14+
static char response[FASTBOOT_RESPONSE_LEN];
1315

1416
static const unsigned short handshake_length = 4;
1517
static const uchar *handshake = "FB01";
1618

17-
static u16 curr_sport;
18-
static u16 curr_dport;
1919
static u32 curr_tcp_seq_num;
2020
static u32 curr_tcp_ack_num;
2121
static unsigned int curr_request_len;
@@ -25,34 +25,37 @@ static enum fastboot_tcp_state {
2525
FASTBOOT_DISCONNECTING
2626
} state = FASTBOOT_CLOSED;
2727

28-
static void fastboot_tcp_answer(u8 action, unsigned int len)
28+
static void fastboot_tcp_answer(struct tcp_stream *tcp, u8 action,
29+
unsigned int len)
2930
{
3031
const u32 response_seq_num = curr_tcp_ack_num;
3132
const u32 response_ack_num = curr_tcp_seq_num +
3233
(curr_request_len > 0 ? curr_request_len : 1);
3334

34-
net_send_tcp_packet(len, htons(curr_sport), htons(curr_dport),
35+
net_send_tcp_packet(len, tcp->rhost, tcp->rport, tcp->lport,
3536
action, response_seq_num, response_ack_num);
3637
}
3738

38-
static void fastboot_tcp_reset(void)
39+
static void fastboot_tcp_reset(struct tcp_stream *tcp)
3940
{
40-
fastboot_tcp_answer(TCP_RST, 0);
41+
fastboot_tcp_answer(tcp, TCP_RST, 0);
4142
state = FASTBOOT_CLOSED;
4243
}
4344

44-
static void fastboot_tcp_send_packet(u8 action, const uchar *data, unsigned int len)
45+
static void fastboot_tcp_send_packet(struct tcp_stream *tcp, u8 action,
46+
const uchar *data, unsigned int len)
4547
{
4648
uchar *pkt = net_get_async_tx_pkt_buf();
4749

4850
memset(pkt, '\0', PKTSIZE);
4951
pkt += net_eth_hdr_size() + IP_TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2;
5052
memcpy(pkt, data, len);
51-
fastboot_tcp_answer(action, len);
53+
fastboot_tcp_answer(tcp, action, len);
5254
memset(pkt, '\0', PKTSIZE);
5355
}
5456

55-
static void fastboot_tcp_send_message(const char *message, unsigned int len)
57+
static void fastboot_tcp_send_message(struct tcp_stream *tcp,
58+
const char *message, unsigned int len)
5659
{
5760
__be64 len_be = __cpu_to_be64(len);
5861
uchar *pkt = net_get_async_tx_pkt_buf();
@@ -63,12 +66,11 @@ static void fastboot_tcp_send_message(const char *message, unsigned int len)
6366
memcpy(pkt, &len_be, 8);
6467
pkt += 8;
6568
memcpy(pkt, message, len);
66-
fastboot_tcp_answer(TCP_ACK | TCP_PUSH, len + 8);
69+
fastboot_tcp_answer(tcp, TCP_ACK | TCP_PUSH, len + 8);
6770
memset(pkt, '\0', PKTSIZE);
6871
}
6972

70-
static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport,
71-
struct in_addr sip, u16 sport,
73+
static void fastboot_tcp_handler_ipv4(struct tcp_stream *tcp, uchar *pkt,
7274
u32 tcp_seq_num, u32 tcp_ack_num,
7375
u8 action, unsigned int len)
7476
{
@@ -77,8 +79,6 @@ static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport,
7779
u8 tcp_fin = action & TCP_FIN;
7880
u8 tcp_push = action & TCP_PUSH;
7981

80-
curr_sport = sport;
81-
curr_dport = dport;
8282
curr_tcp_seq_num = tcp_seq_num;
8383
curr_tcp_ack_num = tcp_ack_num;
8484
curr_request_len = len;
@@ -89,17 +89,17 @@ static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport,
8989
if (len != handshake_length ||
9090
strlen(pkt) != handshake_length ||
9191
memcmp(pkt, handshake, handshake_length) != 0) {
92-
fastboot_tcp_reset();
92+
fastboot_tcp_reset(tcp);
9393
break;
9494
}
95-
fastboot_tcp_send_packet(TCP_ACK | TCP_PUSH,
95+
fastboot_tcp_send_packet(tcp, TCP_ACK | TCP_PUSH,
9696
handshake, handshake_length);
9797
state = FASTBOOT_CONNECTED;
9898
}
9999
break;
100100
case FASTBOOT_CONNECTED:
101101
if (tcp_fin) {
102-
fastboot_tcp_answer(TCP_FIN | TCP_ACK, 0);
102+
fastboot_tcp_answer(tcp, TCP_FIN | TCP_ACK, 0);
103103
state = FASTBOOT_DISCONNECTING;
104104
break;
105105
}
@@ -111,12 +111,12 @@ static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport,
111111

112112
// Only single packet messages are supported ATM
113113
if (strlen(pkt) != command_size) {
114-
fastboot_tcp_reset();
114+
fastboot_tcp_reset(tcp);
115115
break;
116116
}
117117
strlcpy(command, pkt, len + 1);
118118
fastboot_command_id = fastboot_handle_command(command, response);
119-
fastboot_tcp_send_message(response, strlen(response));
119+
fastboot_tcp_send_message(tcp, response, strlen(response));
120120
fastboot_handle_boot(fastboot_command_id,
121121
strncmp("OKAY", response, 4) == 0);
122122
}
@@ -129,17 +129,21 @@ static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport,
129129

130130
memset(command, 0, FASTBOOT_COMMAND_LEN);
131131
memset(response, 0, FASTBOOT_RESPONSE_LEN);
132-
curr_sport = 0;
133-
curr_dport = 0;
134132
curr_tcp_seq_num = 0;
135133
curr_tcp_ack_num = 0;
136134
curr_request_len = 0;
137135
}
138136

137+
static int incoming_filter(struct in_addr rhost, u16 rport, u16 lport)
138+
{
139+
return (lport == FASTBOOT_TCP_PORT);
140+
}
141+
139142
void fastboot_tcp_start_server(void)
140143
{
141144
printf("Using %s device\n", eth_get_name());
142145
printf("Listening for fastboot command on tcp %pI4\n", &net_ip);
143146

147+
tcp_set_incoming_filter(incoming_filter);
144148
tcp_set_tcp_handler(fastboot_tcp_handler_ipv4);
145149
}

net/net.c

+6-6
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ int net_init(void)
420420
/* Only need to setup buffer pointers once. */
421421
first_call = 0;
422422
if (IS_ENABLED(CONFIG_PROT_TCP))
423-
tcp_set_tcp_state(tcp_stream_get(), TCP_CLOSED);
423+
tcp_init();
424424
}
425425

426426
return net_init_loop();
@@ -908,10 +908,10 @@ int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport, int sport,
908908
}
909909

910910
#if defined(CONFIG_PROT_TCP)
911-
int net_send_tcp_packet(int payload_len, int dport, int sport, u8 action,
912-
u32 tcp_seq_num, u32 tcp_ack_num)
911+
int net_send_tcp_packet(int payload_len, struct in_addr dhost, int dport,
912+
int sport, u8 action, u32 tcp_seq_num, u32 tcp_ack_num)
913913
{
914-
return net_send_ip_packet(net_server_ethaddr, net_server_ip, dport,
914+
return net_send_ip_packet(net_server_ethaddr, dhost, dport,
915915
sport, payload_len, IPPROTO_TCP, action,
916916
tcp_seq_num, tcp_ack_num);
917917
}
@@ -953,12 +953,12 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport,
953953
break;
954954
#if defined(CONFIG_PROT_TCP)
955955
case IPPROTO_TCP:
956-
tcp = tcp_stream_get();
956+
tcp = tcp_stream_get(0, dest, dport, sport);
957957
if (!tcp)
958958
return -EINVAL;
959959

960960
pkt_hdr_size = eth_hdr_size
961-
+ tcp_set_tcp_header(tcp, pkt + eth_hdr_size, dport, sport,
961+
+ tcp_set_tcp_header(tcp, pkt + eth_hdr_size,
962962
payload_len, action, tcp_seq_num,
963963
tcp_ack_num);
964964
break;

0 commit comments

Comments
 (0)