FreeBSD/sys/netinet/tcp_input.c
/*
 * Parse TCP options and place in tcpopt.
 */
Parse TCP options and place in tcpopt.
Parse TCP options and place in tcpopt .
void
tcp_dooptions(struct tcpopt *to, u_char *cp, int cnt, int flags)
{
	int opt, optlen;
	to->to_flags = 0;
	for (; cnt > 0; cnt -= optlen, cp += optlen) {
		opt = cp[0];
		if (opt == TCPOPT_EOL)
			break;
		if (opt == TCPOPT_NOP)
			optlen = 1;
		else {
			if (cnt < 2)
				break;
			optlen = cp[1];
			if (optlen < 2 || optlen > cnt)
				break;
		}
		switch (opt) {
		case TCPOPT_MAXSEG:
			if (optlen != TCPOLEN_MAXSEG)
				continue;
			if (!(flags & TO_SYN))
				continue;
			to->to_flags |= TOF_MSS;
			bcopy((char *)cp + 2,
			    (char *)&to->to_mss, sizeof(to->to_mss));
			to->to_mss = ntohs(to->to_mss);
			break;
		case TCPOPT_WINDOW:
			if (optlen != TCPOLEN_WINDOW)
				continue;
			if (!(flags & TO_SYN))
				continue;
			to->to_flags |= TOF_SCALE;
			to->to_wscale = min(cp[2], TCP_MAX_WINSHIFT);
			break;
		case TCPOPT_TIMESTAMP:
			if (optlen != TCPOLEN_TIMESTAMP)
				continue;
			to->to_flags |= TOF_TS;
			bcopy((char *)cp + 2,
			    (char *)&to->to_tsval, sizeof(to->to_tsval));
			to->to_tsval = ntohl(to->to_tsval);
			bcopy((char *)cp + 6,
			    (char *)&to->to_tsecr, sizeof(to->to_tsecr));
			to->to_tsecr = ntohl(to->to_tsecr);
			break;
#ifdef TCP_SIGNATURE
		case TCPOPT_SIGNATURE:
			if (optlen != TCPOLEN_SIGNATURE)
				continue;
			to->to_flags |= TOF_SIGNATURE;
			to->to_signature = cp + 2;
			break;
#endif
		case TCPOPT_SACK_PERMITTED:
			if (optlen != TCPOLEN_SACK_PERMITTED)
				continue;
			if (!(flags & TO_SYN))
				continue;
			if (!V_tcp_do_sack)
				continue;
			to->to_flags |= TOF_SACKPERM;
			break;
		case TCPOPT_SACK:
			if (optlen <= 2 || (optlen - 2) % TCPOLEN_SACK != 0)
				continue;
			if (flags & TO_SYN)
				continue;
			to->to_flags |= TOF_SACK;
			to->to_nsacks = (optlen - 2) / TCPOLEN_SACK;
			to->to_sacks = cp + 2;
			TCPSTAT_INC(tcps_sack_rcv_blocks);
			break;
#ifdef TCP_RFC7413
		case TCPOPT_FAST_OPEN:
			if ((optlen != TCPOLEN_FAST_OPEN_EMPTY) &&
			    (optlen < TCPOLEN_FAST_OPEN_MIN) &&
			    (optlen > TCPOLEN_FAST_OPEN_MAX))
				continue;
			if (!(flags & TO_SYN))
				continue;
			if (!V_tcp_fastopen_enabled)
				continue;
			to->to_flags |= TOF_FASTOPEN;
			to->to_tfo_len = optlen - 2;
			to->to_tfo_cookie = to->to_tfo_len ? cp + 2 : NULL;
			break;
#endif
		default:
			continue;
		}
	}
}
void tcp_dooptions ( struct tcpopt * to , u_char * cp , int cnt , int flags ) { int opt , optlen ; to -> to_flags = 0 ; for ( ; cnt > 0 ; cnt -= optlen , cp += optlen ) { opt = cp [ 0 ] ; if ( opt == TCPOPT_EOL ) break ; if ( opt == TCPOPT_NOP ) optlen = 1 ; else { if ( cnt < 2 ) break ; optlen = cp [ 1 ] ; if ( optlen < 2 || optlen > cnt ) break ; } switch ( opt ) { case TCPOPT_MAXSEG : if ( optlen != TCPOLEN_MAXSEG ) continue ; if ( ! ( flags & TO_SYN ) ) continue ; to -> to_flags |= TOF_MSS ; bcopy ( ( char * ) cp + 2 , ( char * ) & to -> to_mss , sizeof ( to -> to_mss ) ) ; to -> to_mss = ntohs ( to -> to_mss ) ; break ; case TCPOPT_WINDOW : if ( optlen != TCPOLEN_WINDOW ) continue ; if ( ! ( flags & TO_SYN ) ) continue ; to -> to_flags |= TOF_SCALE ; to -> to_wscale = min ( cp [ 2 ] , TCP_MAX_WINSHIFT ) ; break ; case TCPOPT_TIMESTAMP : if ( optlen != TCPOLEN_TIMESTAMP ) continue ; to -> to_flags |= TOF_TS ; bcopy ( ( char * ) cp + 2 , ( char * ) & to -> to_tsval , sizeof ( to -> to_tsval ) ) ; to -> to_tsval = ntohl ( to -> to_tsval ) ; bcopy ( ( char * ) cp + 6 , ( char * ) & to -> to_tsecr , sizeof ( to -> to_tsecr ) ) ; to -> to_tsecr = ntohl ( to -> to_tsecr ) ; break ; #ifdef TCP_SIGNATURE case TCPOPT_SIGNATURE : if ( optlen != TCPOLEN_SIGNATURE ) continue ; to -> to_flags |= TOF_SIGNATURE ; to -> to_signature = cp + 2 ; break ; #endif case TCPOPT_SACK_PERMITTED : if ( optlen != TCPOLEN_SACK_PERMITTED ) continue ; if ( ! ( flags & TO_SYN ) ) continue ; if ( ! V_tcp_do_sack ) continue ; to -> to_flags |= TOF_SACKPERM ; break ; case TCPOPT_SACK : if ( optlen <= 2 || ( optlen - 2 ) % TCPOLEN_SACK != 0 ) continue ; if ( flags & TO_SYN ) continue ; to -> to_flags |= TOF_SACK ; to -> to_nsacks = ( optlen - 2 ) / TCPOLEN_SACK ; to -> to_sacks = cp + 2 ; TCPSTAT_INC ( tcps_sack_rcv_blocks ) ; break ; #ifdef TCP_RFC7413 case TCPOPT_FAST_OPEN : if ( ( optlen != TCPOLEN_FAST_OPEN_EMPTY ) && ( optlen < TCPOLEN_FAST_OPEN_MIN ) && ( optlen > TCPOLEN_FAST_OPEN_MAX ) ) continue ; if ( ! ( flags & TO_SYN ) ) continue ; if ( ! V_tcp_fastopen_enabled ) continue ; to -> to_flags |= TOF_FASTOPEN ; to -> to_tfo_len = optlen - 2 ; to -> to_tfo_cookie = to -> to_tfo_len ? cp + 2 : NULL ; break ; #endif default : continue ; } } }
Parse TCP options and place in tcpopt.
Parse TCP options and place in tcpopt .
/*
		 * XXX In order to reply to a host which has set the
		 * TCP_SIGNATURE option in its initial SYN, we have to
		 * record the fact that the option was observed here
		 * for the syncache code to perform the correct response.
		 */