From patchwork Fri Aug 23 20:45:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kshevetskiy X-Patchwork-Id: 1976258 X-Patchwork-Delegate: rfried.dev@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.a=rsa-sha256 header.s=selector2 header.b=pjgd94c4; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WrBtp4LZ0z1yXY for ; Sat, 24 Aug 2024 06:46:26 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id D4FA788C29; Fri, 23 Aug 2024 22:45:40 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.b="pjgd94c4"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 30D4B88BF2; Fri, 23 Aug 2024 22:45:37 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_PASS, SPF_PASS,T_FILL_THIS_FORM_SHORT,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 Received: from EUR02-VI1-obe.outbound.protection.outlook.com (mail-vi1eur02on2070c.outbound.protection.outlook.com [IPv6:2a01:111:f403:2607::70c]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 8DC7488936 for ; Fri, 23 Aug 2024 22:45:33 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mikhail.kshevetskiy@genexis.eu ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=gs76GF7w8p42/Dx20r/QxrNR64kZUs6SLLWuiayhFIgv9ePMwzHc8kfrtWtoQtAnOp/DTtc6bgYtmsmnI1QCUCkyUxNM+XxfifZfstYYs5sRhbkc/DLInBgaBN3lfTNpso39OlJqeZsckzCTI6xuUbp0erza+qGxnu9PiGt5KvAFaHf88E3Fz0Va8JfNxzOOAJuGyJExefGz3aWaL58qJv8bUMoGvRIrspFFEiUNVKq9HRHeDSaTbLbcsVvsbiA/JmuACqP1uCN0mlciBbQi8Qc44e2kFaVzMtaioGb/X2L6Q9RYXT5+xjvBOQ+E+6oMlTxqZijhLInVKOeUedbXnw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=uQUQRxuC7ZRfmrgfQKZZ0S7oLJ9R/9eQQNAuk0enCMk=; b=g8mJ+5zp+jm6DtmqWmBk4xaSe3lRpWeG7LJgBpcyOnMZywEwLkWz8lhqHPIhVhAOISiSV4F4v231lN/zpkjP1HSzHD/GIMg9jz5273nBX0xomY4tFgUU+13mH+502NnJDYBHcGi5TU0nAK005glDeTcEiXNNJJmiATL09FJtS9xYaqCPn74KnfKRr7r/6oqk9rmch1D8d4KaHWiW5kz72lPXR3hOq6uesj2Z3SfVXOCG/4YKbAJjsAgMZHrjXtYlR5ecRQ9ND9keayfLPbarEDiCvsBRaJINrPs+tq00kVi14ij9nFPnnSDQ7cY8JmSrl9eY9R4Lo2Hdb4HCSw0CAg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=genexis.eu; dmarc=pass action=none header.from=iopsys.eu; dkim=pass header.d=iopsys.eu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iopsys.eu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=uQUQRxuC7ZRfmrgfQKZZ0S7oLJ9R/9eQQNAuk0enCMk=; b=pjgd94c4Wq2z2AyFugUz6WRIRxocmhyxv6+xGEWugYfJBN2zzwZbwSwCoM5r0A1aIr0++cDAe3m0wmaFpVcW7jPDiAtSMQfyueV4G/SaV7LD7wte65X89FHDGGu6Yju5pLQJKfX3/oc2srMKbyksgncpRJbRG9qGJEys2YgovdcQ/Si4HRUqqEKsdzHmBkm64ie39r2fPnXMS0+DvWG2illMPJGPmd04K6tsMk+oXnQPmalwwcT/1lV6434ZeWf33B7fG0cK68286pKkuvPmQioLXc4UT4o3gmYLJeSEDpnC0TSOhVftFUtvWuT3tw4XvAJ3qw20HxHpcwXbzbA8dQ== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=iopsys.eu; Received: from GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) by VI0PR08MB11224.eurprd08.prod.outlook.com (2603:10a6:800:251::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7918.12; Fri, 23 Aug 2024 20:45:32 +0000 Received: from GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0]) by GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0%2]) with mapi id 15.20.7897.010; Fri, 23 Aug 2024 20:45:32 +0000 From: Mikhail Kshevetskiy To: Tom Rini , Joe Hershberger , Ramon Fried , Mattijs Korpershoek , Simon Glass , Heinrich Schuchardt , AKASHI Takahiro , Michal Simek , Francis Laniel , Anand Moon , Marek Vasut , Ilias Apalodimas , Masahisa Kojima , Sean Anderson , Yasuharu Shibata , u-boot@lists.denx.de Subject: [PATCH v4 4/9] net/tcp: add connection info to tcp_stream structure Date: Fri, 23 Aug 2024 23:45:13 +0300 Message-ID: <20240823204518.1010194-5-mikhail.kshevetskiy@iopsys.eu> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240823204518.1010194-1-mikhail.kshevetskiy@iopsys.eu> References: <20240823204518.1010194-1-mikhail.kshevetskiy@iopsys.eu> X-ClientProxiedBy: FR4P281CA0373.DEUP281.PROD.OUTLOOK.COM (2603:10a6:d10:f8::20) To GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: GV2PR08MB8121:EE_|VI0PR08MB11224:EE_ X-MS-Office365-Filtering-Correlation-Id: 462e3598-7d59-4989-5c2c-08dcc3b487cd X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|366016|7416014|52116014|376014|1800799024|38350700014|921020; X-Microsoft-Antispam-Message-Info: 9ORYLMcXHnJZgXgjlKmhdwlY9x05fdZF/jwtwR8CzaQb2KCoOmrS+Ml/xqEQz6QFWzckHhCjeW9oWmuVjiXD8eorqoxC34iPEmW7Xew1LLZgnOE4V8iJ0jCwNVFQIQNLZs5J5EUWxT6FPmMM93FvZ+klk+CYTRMpKC9jvIqR94RsVH/DRAUzAzTKsdbaOIL1W/MOEYLA7JetQ1LeD2ZATwrln9dw0xsYsfEjRE25qLDwQxY6TtDZdS209N4N4S9vBfNLElFpCy+eNxSCuRn3DMbOKKqN7HDLn+YfaY/dGLwbUI7FF7AF15zDDeJUD11tAOJMR9LW8q4Bst5pixZLHvv8YVrWJ7QxJA6AOkkgqAIwnhA0WMAJI2eiIhrW42TBGsAf+1wzD9k58kHZJL6xVueWC8lARVUwSR7+icvdfPVWfBMafM1ng55PZ8ZjLbAkFhEXkzukWBHGcZW8Eifr29MMX5VlUSrPM2xrwVoWbyobdaTZpMqVSvPCYbtbIdZLrH0sYQJdjx5x3ZnuSWwcvlxWzPvpf1nzS7n61IjqpACrcM+Y/bBAKUX+bffWTnz9Y/0W2H0G91jqBd+l+YHJvhZgdl29dI8LiVs/tEhTLfjTIhMn/piRMJvhZhyhVFUei8957P3w/3nXGu4G/lQ6qGIb4rge28UnVLyOp4Ws0k1leFtjyy/dDMPsOGBN7/xikfGMpMIGYRANVCu/FS9g7O9yx3Y05WKKk17q60hyg2ndRx5GA8gWgwYgHp/6akXap9wXhlsCKouAA0LNxSq5lRsrLDJIFZyUqlNQpa8egDR7wdEKn8My7f8LKF90rBvSRHLL/xajQooQLAMxfu9HR4Tx8MPyVrJt+9wonU/9KKkSfcmTTVYsb68uoFRBvJlAhCqOyUeJXDAKTSzOF8rMzO0hsOI8psCruk4SdAH388Xp7h3kCa8xu6uZK3bslnrSPe5dJiFW3pYaThDkAV8buKKcAB2tcsuYYpegD6rvjvYsTGKfKH+6uk9FUxMuHgFJiYF0rKpE9pHV3mdXgz6FTUL6D0Ak2AsQuwAgIMBrEYks//cRtS6CeUwm/fjJxfwftoYX43TFhVoB3oQ1ZbDCtwlxYtwMo81GQm+qCmKqu1OyWFEoUjsgEKKAbF/zf0+bMa5AYgZ8pT7AUOC4B3izbAaWN/K6Ad8eBgzCgKB0arHlanugwFmDevFSK/E8oO6AKDRrbIQx9rqdBNe82pvI0nYv4Ko+Wa9TEOuiD4xNk2HGjLT9NYhrOw51KdT/Efy/dscnOQQccY83VCyWJCWKKRuoVazzVVcdXtSR5K640gEYHaRR+jT0c+StUl9lM9mk58Q3XbRr3G/XIiLSXWHLvM9APEdh7Jo4F1OrxKkFZ+h/epHW828Rt9ch0p4yCnJFnFLF6fetrliy4ctmafSpXPeasgG/puK2ltYzYZgw5go= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GV2PR08MB8121.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(366016)(7416014)(52116014)(376014)(1800799024)(38350700014)(921020); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: AvWE2qpbRUTTfq0ITtxus5711cTDjWcGfy/SrHekVq2/xJIWOhYjY2bGeUgpq8SSOC5Emu/+mWdh6yjDw2DssGN4mOov8Il9XBGQZASNQRhdIqP7uKeImaQV8R9h27McML5xGIAkvTltad66ahDTt05ulF69UC09A6nZhzOa4kbDPlon6yNUKDrZbuRh+tmrHF7XobItRA6tMfdR5Nk4FpBaZrViUAgieKv2Lt9rtwAF2ESjiwUh0JC6dyETwBt1Pp91Q0RhMqez4QAVHb7Gd/cf3WXogPHJeKbkeCUtxrhg/835PQkbc5eovixm2IdAXo7JC1t9vLU3Frdge5bEbwVyXfjiEjZZ0E46fOombbqpAnz0pe5bqAFNFyJJOGeuKHMHWTRsPRL7zp+nyO6pfz3f4+TWV1TJrTs443fr0ut41+iKGJuTvg2rz6On4Ie1a5SQ9caE6QrUuQ/D5tlnpWH88ioQxht3x4ZjmAzIiq5ZUP45IkZFC83b7bLG3YQiCZ+pmvkWVKGJvImnq/yQm4c5UzZd5+VFutexCA+5uiglYFFXxLi1NvQ9l1txfrL2QB/BwAsHsUSASmI12ilOsaTeFfQCb7HTIqQILPvKOVZW0OmQZhSs/MU28/WKzLGIZUCBBYe8AVHjhouu7v+Pg5MG9BFWSVUbQff5+Un9Du+GW77h8Nui0aocvInC/phe0DXBud7if8zufbE3B1/Yu3mdoLtMeWUeAGBf1pKIn/fcEklqN3G72sYBokoqU9+LMY4Nf/Pa+ZvVHthzgiADBXps9pKCfNdwH8qVrU2zgzPWx3a2kchkAhbIJTebDubtT7CFQ/R6zbqLxIe2HTvu8SGMOeIOEK7wquV/oEZpE807dUg72Sa2LpSqyk4mlImBd/54QQ1Bk0OUbNHyZ7jfzA7xZPerLFLMu2SaOLZJTmw5Fmll4DbopHoAoFD7UUnL/Ok9B6NN65SNsNozYmGXCIFuANFQL7BHQmmwxvBZqmQtMaj4FwULycIzQvJov6SAIfy3eq9TC6AXECEteRV+7YegbZD1Wm2kqDzPBBR8VCt/E0J6wmaJnRshErHt+83/k6xeMyzCrDhtpGXDFGxdzlLcGeBy+PskO08vwMEOu3lUXtYpf6NBdAfXAzACaPNCnlNNf8BQXfM8AaffZPlgGr6aQ7wQXZvai0x9LjtEbjsDKD6DBF17Sb9fUlkAzTi7tdXOYwA25Yle+nwDvBHhjsjsX4kB1WEDxNJDgKCXrjsm+4qUU0/k8oXrJjy2Hq56v9/rlKq78AWwg43hWeXY2v0NgBGgxR42FG+q2HhkuYqFrUE5ROJVLbhjG98xu//6AkrfJDLna63081Zyo3qtxvP5s6pcdN0OWxB5vmQ/1MCF/qv5vJT82MIf3wI3rfE1m3k9HX4yCS/dXJpw4TwjNbY6nejFV72pRW+RkMfvqMhvOwPQj6OtgiYEf43xaAR0301/uf5le43LTH0/zsUyOqibJvSGqCoUxC90gSIG9hxkH1zvp7+vpWtG+pJmYnzZ/gELQ3TabIBTX/Wh7zNVmCrt5ZK2fryqCWr63wB9A2UcaLErApo1q3AFMCf8pc9RFeb2cfgjIWHzThbfhpHdKG4RSNYONpV8xLqIOQqtJvI= X-OriginatorOrg: iopsys.eu X-MS-Exchange-CrossTenant-Network-Message-Id: 462e3598-7d59-4989-5c2c-08dcc3b487cd X-MS-Exchange-CrossTenant-AuthSource: GV2PR08MB8121.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 23 Aug 2024 20:45:32.1479 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8d891be1-7bce-4216-9a99-bee9de02ba58 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: TyMYwyvKyvr9LD53HOCszFRXQ/K3gIfRCz27lOCaNqhaq0rJsb2Ou17R+XXM3dTjjoJUP4lgef/9DMd7VoB4d2A+uj0jSF6VILLwPX0U2QQ= X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI0PR08MB11224 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean 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 Reviewed-by: Simon Glass --- include/net.h | 5 +- include/net/tcp.h | 57 +++++++++++++++++--- net/fastboot_tcp.c | 46 ++++++++-------- net/net.c | 12 ++--- net/tcp.c | 129 ++++++++++++++++++++++++++++++++++----------- net/wget.c | 52 +++++++----------- 6 files changed, 201 insertions(+), 100 deletions(-) diff --git a/include/net.h b/include/net.h index bb2ae20f52a..b0ce13e0a9d 100644 --- a/include/net.h +++ b/include/net.h @@ -667,6 +667,7 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, /** * net_send_tcp_packet() - Transmit TCP packet. * @payload_len: length of payload + * @dhost: Destination host * @dport: Destination TCP port * @sport: Source TCP port * @action: TCP action to be performed @@ -675,8 +676,8 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, * * Return: 0 on success, other value on failure */ -int net_send_tcp_packet(int payload_len, int dport, int sport, u8 action, - u32 tcp_seq_num, u32 tcp_ack_num); +int net_send_tcp_packet(int payload_len, struct in_addr dhost, int dport, + int sport, u8 action, u32 tcp_seq_num, u32 tcp_ack_num); int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport, int sport, int payload_len); diff --git a/include/net/tcp.h b/include/net/tcp.h index 14aee64cb1c..f224d0cae2f 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -279,6 +279,9 @@ enum tcp_state { /** * struct tcp_stream - TCP data stream structure + * @rhost: Remote host, network byte order + * @rport: Remote port, host byte order + * @lport: Local port, host byte order * * @state: TCP connection state * @@ -291,6 +294,10 @@ enum tcp_state { * @lost: Used for SACK */ struct tcp_stream { + struct in_addr rhost; + u16 rport; + u16 lport; + /* TCP connection state */ enum tcp_state state; @@ -305,16 +312,53 @@ struct tcp_stream { struct tcp_sack_v lost; }; -struct tcp_stream *tcp_stream_get(void); +void tcp_init(void); + +typedef int tcp_incoming_filter(struct in_addr rhost, + u16 rport, u16 sport); + +/* + * This function sets user callback used to accept/drop incoming + * connections. Callback should: + * + Check TCP stream endpoint and make connection verdict + * - return non-zero value to accept connection + * - return zero to drop connection + * + * WARNING: If callback is NOT defined, all incoming connections + * will be dropped. + */ +void tcp_set_incoming_filter(tcp_incoming_filter *filter); + +/* + * tcp_stream_get -- Get or create TCP stream + * @is_new: if non-zero and no stream found, then create a new one + * @rhost: Remote host, network byte order + * @rport: Remote port, host byte order + * @lport: Local port, host byte order + * + * Returns: TCP stream structure or NULL (if not found/created) + */ +struct tcp_stream *tcp_stream_get(int is_new, struct in_addr rhost, + u16 rport, u16 lport); + +/* + * tcp_stream_connect -- Create new TCP stream for remote connection. + * @rhost: Remote host, network byte order + * @rport: Remote port, host byte order + * + * Returns: TCP new stream structure or NULL (if not created). + * Random local port will be used. + */ +struct tcp_stream *tcp_stream_connect(struct in_addr rhost, u16 rport); + +enum tcp_state tcp_stream_get_state(struct tcp_stream *tcp); -enum tcp_state tcp_get_tcp_state(struct tcp_stream *tcp); -void tcp_set_tcp_state(struct tcp_stream *tcp, enum tcp_state new_state); -int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, - int sport, int payload_len, +int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int payload_len, u8 action, u32 tcp_seq_num, u32 tcp_ack_num); /** * rxhand_tcp() - An incoming packet handler. + * @tcp: TCP stream * @pkt: pointer to the application packet * @dport: destination TCP port * @sip: source IP address @@ -324,8 +368,7 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, * @action: TCP action (SYN, ACK, FIN, etc) * @len: packet length */ -typedef void rxhand_tcp(uchar *pkt, u16 dport, - struct in_addr sip, u16 sport, +typedef void rxhand_tcp(struct tcp_stream *tcp, uchar *pkt, u32 tcp_seq_num, u32 tcp_ack_num, u8 action, unsigned int len); void tcp_set_tcp_handler(rxhand_tcp *f); diff --git a/net/fastboot_tcp.c b/net/fastboot_tcp.c index d1fccbc7238..12a4d6690be 100644 --- a/net/fastboot_tcp.c +++ b/net/fastboot_tcp.c @@ -8,14 +8,14 @@ #include #include +#define FASTBOOT_TCP_PORT 5554 + static char command[FASTBOOT_COMMAND_LEN] = {0}; static char response[FASTBOOT_RESPONSE_LEN] = {0}; static const unsigned short handshake_length = 4; static const uchar *handshake = "FB01"; -static u16 curr_sport; -static u16 curr_dport; static u32 curr_tcp_seq_num; static u32 curr_tcp_ack_num; static unsigned int curr_request_len; @@ -25,34 +25,37 @@ static enum fastboot_tcp_state { FASTBOOT_DISCONNECTING } state = FASTBOOT_CLOSED; -static void fastboot_tcp_answer(u8 action, unsigned int len) +static void fastboot_tcp_answer(struct tcp_stream *tcp, u8 action, + unsigned int len) { const u32 response_seq_num = curr_tcp_ack_num; const u32 response_ack_num = curr_tcp_seq_num + (curr_request_len > 0 ? curr_request_len : 1); - net_send_tcp_packet(len, htons(curr_sport), htons(curr_dport), + net_send_tcp_packet(len, tcp->rhost, tcp->rport, tcp->lport, action, response_seq_num, response_ack_num); } -static void fastboot_tcp_reset(void) +static void fastboot_tcp_reset(struct tcp_stream *tcp) { - fastboot_tcp_answer(TCP_RST, 0); + fastboot_tcp_answer(tcp, TCP_RST, 0); state = FASTBOOT_CLOSED; } -static void fastboot_tcp_send_packet(u8 action, const uchar *data, unsigned int len) +static void fastboot_tcp_send_packet(struct tcp_stream *tcp, u8 action, + const uchar *data, unsigned int len) { uchar *pkt = net_get_async_tx_pkt_buf(); memset(pkt, '\0', PKTSIZE); pkt += net_eth_hdr_size() + IP_TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2; memcpy(pkt, data, len); - fastboot_tcp_answer(action, len); + fastboot_tcp_answer(tcp, action, len); memset(pkt, '\0', PKTSIZE); } -static void fastboot_tcp_send_message(const char *message, unsigned int len) +static void fastboot_tcp_send_message(struct tcp_stream *tcp, + const char *message, unsigned int len) { __be64 len_be = __cpu_to_be64(len); uchar *pkt = net_get_async_tx_pkt_buf(); @@ -63,12 +66,11 @@ static void fastboot_tcp_send_message(const char *message, unsigned int len) memcpy(pkt, &len_be, 8); pkt += 8; memcpy(pkt, message, len); - fastboot_tcp_answer(TCP_ACK | TCP_PUSH, len + 8); + fastboot_tcp_answer(tcp, TCP_ACK | TCP_PUSH, len + 8); memset(pkt, '\0', PKTSIZE); } -static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport, - struct in_addr sip, u16 sport, +static void fastboot_tcp_handler_ipv4(struct tcp_stream *tcp, uchar *pkt, u32 tcp_seq_num, u32 tcp_ack_num, u8 action, unsigned int len) { @@ -77,8 +79,6 @@ static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport, u8 tcp_fin = action & TCP_FIN; u8 tcp_push = action & TCP_PUSH; - curr_sport = sport; - curr_dport = dport; curr_tcp_seq_num = tcp_seq_num; curr_tcp_ack_num = tcp_ack_num; curr_request_len = len; @@ -89,17 +89,17 @@ static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport, if (len != handshake_length || strlen(pkt) != handshake_length || memcmp(pkt, handshake, handshake_length) != 0) { - fastboot_tcp_reset(); + fastboot_tcp_reset(tcp); break; } - fastboot_tcp_send_packet(TCP_ACK | TCP_PUSH, + fastboot_tcp_send_packet(tcp, TCP_ACK | TCP_PUSH, handshake, handshake_length); state = FASTBOOT_CONNECTED; } break; case FASTBOOT_CONNECTED: if (tcp_fin) { - fastboot_tcp_answer(TCP_FIN | TCP_ACK, 0); + fastboot_tcp_answer(tcp, TCP_FIN | TCP_ACK, 0); state = FASTBOOT_DISCONNECTING; break; } @@ -111,12 +111,12 @@ static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport, // Only single packet messages are supported ATM if (strlen(pkt) != command_size) { - fastboot_tcp_reset(); + fastboot_tcp_reset(tcp); break; } strlcpy(command, pkt, len + 1); fastboot_command_id = fastboot_handle_command(command, response); - fastboot_tcp_send_message(response, strlen(response)); + fastboot_tcp_send_message(tcp, response, strlen(response)); fastboot_handle_boot(fastboot_command_id, strncmp("OKAY", response, 4) == 0); } @@ -129,17 +129,21 @@ static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport, memset(command, 0, FASTBOOT_COMMAND_LEN); memset(response, 0, FASTBOOT_RESPONSE_LEN); - curr_sport = 0; - curr_dport = 0; curr_tcp_seq_num = 0; curr_tcp_ack_num = 0; curr_request_len = 0; } +static int incoming_filter(struct in_addr rhost, u16 rport, u16 lport) +{ + return (lport == FASTBOOT_TCP_PORT); +} + void fastboot_tcp_start_server(void) { printf("Using %s device\n", eth_get_name()); printf("Listening for fastboot command on tcp %pI4\n", &net_ip); + tcp_set_incoming_filter(incoming_filter); tcp_set_tcp_handler(fastboot_tcp_handler_ipv4); } diff --git a/net/net.c b/net/net.c index 6c5ee7e0925..b33ea59a9fa 100644 --- a/net/net.c +++ b/net/net.c @@ -414,7 +414,7 @@ int net_init(void) /* Only need to setup buffer pointers once. */ first_call = 0; if (IS_ENABLED(CONFIG_PROT_TCP)) - tcp_set_tcp_state(tcp_stream_get(), TCP_CLOSED); + tcp_init(); } return net_init_loop(); @@ -899,10 +899,10 @@ int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport, int sport, } #if defined(CONFIG_PROT_TCP) -int net_send_tcp_packet(int payload_len, int dport, int sport, u8 action, - u32 tcp_seq_num, u32 tcp_ack_num) +int net_send_tcp_packet(int payload_len, struct in_addr dhost, int dport, + int sport, u8 action, u32 tcp_seq_num, u32 tcp_ack_num) { - return net_send_ip_packet(net_server_ethaddr, net_server_ip, dport, + return net_send_ip_packet(net_server_ethaddr, dhost, dport, sport, payload_len, IPPROTO_TCP, action, tcp_seq_num, tcp_ack_num); } @@ -944,12 +944,12 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, break; #if defined(CONFIG_PROT_TCP) case IPPROTO_TCP: - tcp = tcp_stream_get(); + tcp = tcp_stream_get(0, dest, dport, sport); if (tcp == NULL) return -EINVAL; pkt_hdr_size = eth_hdr_size - + tcp_set_tcp_header(tcp, pkt + eth_hdr_size, dport, sport, + + tcp_set_tcp_header(tcp, pkt + eth_hdr_size, payload_len, action, tcp_seq_num, tcp_ack_num); break; diff --git a/net/tcp.c b/net/tcp.c index 6646f171b83..9acf9f3ccb2 100644 --- a/net/tcp.c +++ b/net/tcp.c @@ -26,6 +26,7 @@ static int tcp_activity_count; static struct tcp_stream tcp_stream; +static tcp_incoming_filter *incoming_filter; /* * TCP lengths are stored as a rounded up number of 32 bit words. @@ -40,40 +41,95 @@ static struct tcp_stream tcp_stream; /* Current TCP RX packet handler */ static rxhand_tcp *tcp_packet_handler; +#define RANDOM_PORT_START 1024 +#define RANDOM_PORT_RANGE 0x4000 + +/** + * random_port() - make port a little random (1024-17407) + * + * Return: random port number from 1024 to 17407 + * + * This keeps the math somewhat trivial to compute, and seems to work with + * all supported protocols/clients/servers + */ +static unsigned int random_port(void) +{ + return RANDOM_PORT_START + (get_timer(0) % RANDOM_PORT_RANGE); +} + static inline s32 tcp_seq_cmp(u32 a, u32 b) { return (s32)(a - b); } /** - * tcp_get_tcp_state() - get TCP stream state + * tcp_stream_get_state() - get TCP stream state * @tcp: tcp stream * * Return: TCP stream state */ -enum tcp_state tcp_get_tcp_state(struct tcp_stream *tcp) +enum tcp_state tcp_stream_get_state(struct tcp_stream *tcp) { return tcp->state; } /** - * tcp_set_tcp_state() - set TCP stream state + * tcp_stream_set_state() - set TCP stream state * @tcp: tcp stream * @new_state: new TCP state */ -void tcp_set_tcp_state(struct tcp_stream *tcp, - enum tcp_state new_state) +static void tcp_stream_set_state(struct tcp_stream *tcp, + enum tcp_state new_state) { tcp->state = new_state; } -struct tcp_stream *tcp_stream_get(void) +void tcp_init(void) +{ + incoming_filter = NULL; + tcp_stream.state = TCP_CLOSED; +} + +void tcp_set_incoming_filter(tcp_incoming_filter *filter) +{ + incoming_filter = filter; +} + +static struct tcp_stream *tcp_stream_add(struct in_addr rhost, + u16 rport, u16 lport) +{ + struct tcp_stream *tcp = &tcp_stream; + + if (tcp->state != TCP_CLOSED) + return NULL; + + memset(tcp, 0, sizeof(struct tcp_stream)); + tcp->rhost.s_addr = rhost.s_addr; + tcp->rport = rport; + tcp->lport = lport; + tcp->state = TCP_CLOSED; + tcp->lost.len = TCP_OPT_LEN_2; + return tcp; +} + +struct tcp_stream *tcp_stream_get(int is_new, struct in_addr rhost, + u16 rport, u16 lport) { - return &tcp_stream; + struct tcp_stream *tcp = &tcp_stream; + + if ((tcp->rhost.s_addr == rhost.s_addr) && + (tcp->rport == rport) && + (tcp->lport == lport)) + return tcp; + + if (!is_new || (incoming_filter == NULL) || + !incoming_filter(rhost, rport, lport)) + return NULL; + + return tcp_stream_add(rhost, rport, lport); } -static void dummy_handler(uchar *pkt, u16 dport, - struct in_addr sip, u16 sport, +static void dummy_handler(struct tcp_stream *tcp, uchar *pkt, u32 tcp_seq_num, u32 tcp_ack_num, u8 action, unsigned int len) { @@ -222,8 +278,7 @@ void net_set_syn_options(struct tcp_stream *tcp, union tcp_build_pkt *b) b->ip.end = TCP_O_END; } -int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, - int sport, int payload_len, +int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int payload_len, u8 action, u32 tcp_seq_num, u32 tcp_ack_num) { union tcp_build_pkt *b = (union tcp_build_pkt *)pkt; @@ -243,7 +298,7 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, case TCP_SYN: debug_cond(DEBUG_DEV_PKT, "TCP Hdr:SYN (%pI4, %pI4, sq=%u, ak=%u)\n", - &net_server_ip, &net_ip, + &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num); tcp_activity_count = 0; net_set_syn_options(tcp, b); @@ -264,13 +319,13 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, b->ip.hdr.tcp_flags = action; debug_cond(DEBUG_DEV_PKT, "TCP Hdr:ACK (%pI4, %pI4, s=%u, a=%u, A=%x)\n", - &net_server_ip, &net_ip, tcp_seq_num, tcp_ack_num, + &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num, action); break; case TCP_FIN: debug_cond(DEBUG_DEV_PKT, "TCP Hdr:FIN (%pI4, %pI4, s=%u, a=%u)\n", - &net_server_ip, &net_ip, tcp_seq_num, tcp_ack_num); + &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num); payload_len = 0; pkt_hdr_len = IP_TCP_HDR_SIZE; tcp->state = TCP_FIN_WAIT_1; @@ -279,7 +334,7 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, case TCP_RST: debug_cond(DEBUG_DEV_PKT, "TCP Hdr:RST (%pI4, %pI4, s=%u, a=%u)\n", - &net_server_ip, &net_ip, tcp_seq_num, tcp_ack_num); + &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num); tcp->state = TCP_CLOSED; break; /* Notify connection closing */ @@ -290,7 +345,7 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, debug_cond(DEBUG_DEV_PKT, "TCP Hdr:FIN ACK PSH(%pI4, %pI4, s=%u, a=%u, A=%x)\n", - &net_server_ip, &net_ip, + &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num, action); fallthrough; default: @@ -298,7 +353,7 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, b->ip.hdr.tcp_flags = action | TCP_PUSH | TCP_ACK; debug_cond(DEBUG_DEV_PKT, "TCP Hdr:dft (%pI4, %pI4, s=%u, a=%u, A=%x)\n", - &net_server_ip, &net_ip, + &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num, action); } @@ -308,8 +363,8 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, tcp->ack_edge = tcp_ack_num; /* TCP Header */ b->ip.hdr.tcp_ack = htonl(tcp->ack_edge); - b->ip.hdr.tcp_src = htons(sport); - b->ip.hdr.tcp_dst = htons(dport); + b->ip.hdr.tcp_src = htons(tcp->lport); + b->ip.hdr.tcp_dst = htons(tcp->rport); b->ip.hdr.tcp_seq = htonl(tcp_seq_num); /* @@ -332,10 +387,10 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport, b->ip.hdr.tcp_xsum = 0; b->ip.hdr.tcp_ugr = 0; - b->ip.hdr.tcp_xsum = tcp_set_pseudo_header(pkt, net_ip, net_server_ip, + b->ip.hdr.tcp_xsum = tcp_set_pseudo_header(pkt, net_ip, tcp->rhost, tcp_len, pkt_len); - net_set_ip_header((uchar *)&b->ip, net_server_ip, net_ip, + net_set_ip_header((uchar *)&b->ip, tcp->rhost, net_ip, pkt_len, IPPROTO_TCP); return pkt_hdr_len; @@ -616,19 +671,26 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len) u32 tcp_seq_num, tcp_ack_num; int tcp_hdr_len, payload_len; struct tcp_stream *tcp; + struct in_addr src; /* Verify IP header */ debug_cond(DEBUG_DEV_PKT, "TCP RX in RX Sum (to=%pI4, from=%pI4, len=%d)\n", &b->ip.hdr.ip_src, &b->ip.hdr.ip_dst, pkt_len); - b->ip.hdr.ip_src = net_server_ip; + /* + * src IP address will be destroyed by TCP checksum verification + * algorithm (see tcp_set_pseudo_header()), so remember it before + * it was garbaged. + */ + src.s_addr = b->ip.hdr.ip_src.s_addr; + b->ip.hdr.ip_dst = net_ip; b->ip.hdr.ip_sum = 0; if (tcp_rx_xsum != compute_ip_checksum(b, IP_HDR_SIZE)) { debug_cond(DEBUG_DEV_PKT, "TCP RX IP xSum Error (%pI4, =%pI4, len=%d)\n", - &net_ip, &net_server_ip, pkt_len); + &net_ip, &src, pkt_len); return; } @@ -640,11 +702,14 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len) pkt_len)) { debug_cond(DEBUG_DEV_PKT, "TCP RX TCP xSum Error (%pI4, %pI4, len=%d)\n", - &net_ip, &net_server_ip, tcp_len); + &net_ip, &src, tcp_len); return; } - tcp = tcp_stream_get(); + tcp = tcp_stream_get(b->ip.hdr.tcp_flags & TCP_SYN, + src, + ntohs(b->ip.hdr.tcp_src), + ntohs(b->ip.hdr.tcp_dst)); if (tcp == NULL) return; @@ -676,9 +741,9 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len) "TCP Notify (action=%x, Seq=%u,Ack=%u,Pay%d)\n", tcp_action, tcp_seq_num, tcp_ack_num, payload_len); - (*tcp_packet_handler) ((uchar *)b + pkt_len - payload_len, b->ip.hdr.tcp_dst, - b->ip.hdr.ip_src, b->ip.hdr.tcp_src, tcp_seq_num, - tcp_ack_num, tcp_action, payload_len); + (*tcp_packet_handler) (tcp, (uchar *)b + pkt_len - payload_len, + tcp_seq_num, tcp_ack_num, tcp_action, + payload_len); } else if (tcp_action != TCP_DATA) { debug_cond(DEBUG_DEV_PKT, @@ -689,9 +754,13 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len) * Warning: Incoming Ack & Seq sequence numbers are transposed * here to outgoing Seq & Ack sequence numbers */ - net_send_tcp_packet(0, ntohs(b->ip.hdr.tcp_src), - ntohs(b->ip.hdr.tcp_dst), + net_send_tcp_packet(0, tcp->rhost, tcp->rport, tcp->lport, (tcp_action & (~TCP_PUSH)), tcp_ack_num, tcp->ack_edge); } } + +struct tcp_stream *tcp_stream_connect(struct in_addr rhost, u16 rport) +{ + return tcp_stream_add(rhost, rport, random_port()); +} diff --git a/net/wget.c b/net/wget.c index c0a80597bfe..ad5db21e97e 100644 --- a/net/wget.c +++ b/net/wget.c @@ -27,9 +27,8 @@ static const char http_eom[] = "\r\n\r\n"; static const char http_ok[] = "200"; static const char content_len[] = "Content-Length"; static const char linefeed[] = "\r\n"; -static struct in_addr web_server_ip; -static int our_port; static int wget_timeout_count; +struct tcp_stream *tcp; struct pkt_qd { uchar *pkt; @@ -137,22 +136,19 @@ static void wget_send_stored(void) int len = retry_len; unsigned int tcp_ack_num = retry_tcp_seq_num + (len == 0 ? 1 : len); unsigned int tcp_seq_num = retry_tcp_ack_num; - unsigned int server_port; uchar *ptr, *offset; - server_port = env_get_ulong("httpdstp", 10, SERVER_PORT) & 0xffff; - switch (current_wget_state) { case WGET_CLOSED: debug_cond(DEBUG_WGET, "wget: send SYN\n"); current_wget_state = WGET_CONNECTING; - net_send_tcp_packet(0, server_port, our_port, action, + net_send_tcp_packet(0, tcp->rhost, tcp->rport, tcp->lport, action, tcp_seq_num, tcp_ack_num); packets = 0; break; case WGET_CONNECTING: pkt_q_idx = 0; - net_send_tcp_packet(0, server_port, our_port, action, + net_send_tcp_packet(0, tcp->rhost, tcp->rport, tcp->lport, action, tcp_seq_num, tcp_ack_num); ptr = net_tx_packet + net_eth_hdr_size() + @@ -167,14 +163,14 @@ static void wget_send_stored(void) memcpy(offset, &bootfile3, strlen(bootfile3)); offset += strlen(bootfile3); - net_send_tcp_packet((offset - ptr), server_port, our_port, + net_send_tcp_packet((offset - ptr), tcp->rhost, tcp->rport, tcp->lport, TCP_PUSH, tcp_seq_num, tcp_ack_num); current_wget_state = WGET_CONNECTED; break; case WGET_CONNECTED: case WGET_TRANSFERRING: case WGET_TRANSFERRED: - net_send_tcp_packet(0, server_port, our_port, action, + net_send_tcp_packet(0, tcp->rhost, tcp->rport, tcp->lport, action, tcp_seq_num, tcp_ack_num); break; } @@ -339,10 +335,8 @@ static void wget_connected(uchar *pkt, unsigned int tcp_seq_num, /** * wget_handler() - TCP handler of wget + * @tcp: TCP stream * @pkt: pointer to the application packet - * @dport: destination TCP port - * @sip: source IP address - * @sport: source TCP port * @tcp_seq_num: TCP sequential number * @tcp_ack_num: TCP acknowledgment number * @action: TCP action (SYN, ACK, FIN, etc) @@ -351,13 +345,11 @@ static void wget_connected(uchar *pkt, unsigned int tcp_seq_num, * In the "application push" invocation, the TCP header with all * its information is pointed to by the packet pointer. */ -static void wget_handler(uchar *pkt, u16 dport, - struct in_addr sip, u16 sport, +static void wget_handler(struct tcp_stream *tcp, uchar *pkt, u32 tcp_seq_num, u32 tcp_ack_num, u8 action, unsigned int len) { - struct tcp_stream *tcp = tcp_stream_get(); - enum tcp_state wget_tcp_state = tcp_get_tcp_state(tcp); + enum tcp_state wget_tcp_state = tcp_stream_get_state(tcp); net_set_timeout_handler(wget_timeout, wget_timeout_handler); packets++; @@ -441,26 +433,13 @@ static void wget_handler(uchar *pkt, u16 dport, } } -#define RANDOM_PORT_START 1024 -#define RANDOM_PORT_RANGE 0x4000 - -/** - * random_port() - make port a little random (1024-17407) - * - * Return: random port number from 1024 to 17407 - * - * This keeps the math somewhat trivial to compute, and seems to work with - * all supported protocols/clients/servers - */ -static unsigned int random_port(void) -{ - return RANDOM_PORT_START + (get_timer(0) % RANDOM_PORT_RANGE); -} - #define BLOCKSIZE 512 void wget_start(void) { + struct in_addr web_server_ip; + unsigned int server_port; + image_url = strchr(net_boot_file_name, ':'); if (image_url > 0) { web_server_ip = string_to_ip(net_boot_file_name); @@ -513,8 +492,6 @@ void wget_start(void) wget_timeout_count = 0; current_wget_state = WGET_CLOSED; - our_port = random_port(); - /* * Zero out server ether to force arp resolution in case * the server ip for the previous u-boot command, for example dns @@ -523,6 +500,13 @@ void wget_start(void) memset(net_server_ethaddr, 0, 6); + server_port = env_get_ulong("httpdstp", 10, SERVER_PORT) & 0xffff; + tcp = tcp_stream_connect(web_server_ip, server_port); + if (tcp == NULL) { + net_set_state(NETLOOP_FAIL); + return; + } + wget_send(TCP_SYN, 0, 0, 0); }