DBGC ( conn, "\n" );
/* Transmit packet */
- return tcpip_tx ( pkb, &tcp_protocol, &conn->peer );
+ return tcpip_tx ( pkb, &tcp_protocol, &conn->peer, &tcphdr->csum );
}
/**
* Process received packet
*
* @v pkb Packet buffer
- * @v partial Partial checksum
- */
+ * @v st_src Partially-filled source address
+ * @v st_dest Partially-filled destination address
+ * @v pshdr_csum Pseudo-header checksum
+ * @ret rc Return status code
+ */
static int tcp_rx ( struct pk_buff *pkb,
struct sockaddr_tcpip *st_src __unused,
- struct sockaddr_tcpip *st_dest __unused ) {
+ struct sockaddr_tcpip *st_dest __unused,
+ uint16_t pshdr_csum ) {
struct tcp_header *tcphdr;
struct tcp_connection *conn;
unsigned int hlen;
+ uint16_t csum;
uint32_t start_seq;
uint32_t seq;
uint32_t ack;
size_t len;
int rc = 0;
- /* Sanity check packet and strip TCP header */
+ /* Sanity check packet */
if ( pkb_len ( pkb ) < sizeof ( *tcphdr ) ) {
DBG ( "TCP packet too short at %d bytes (min %d bytes)\n",
pkb_len ( pkb ), sizeof ( *tcphdr ) );
rc = -EINVAL;
goto err;
}
-
- /* TODO: Verify checksum */
-#warning "Verify checksum"
+ csum = tcpip_continue_chksum ( pshdr_csum, pkb->data, pkb_len ( pkb ));
+ if ( csum != 0 ) {
+ DBG ( "TCP checksum incorrect (is %04x including checksum "
+ "field, should be 0000)\n", csum );
+ goto err;
+ }
/* Parse parameters from header and strip header */
conn = tcp_demux ( tcphdr->dest );
.name = "TCP",
.rx = tcp_rx,
.tcpip_proto = IP_TCP,
- .csum_offset = 16,
};