Re: refactor PF option parsing loops

2017-01-24 Thread Martin Pieuchot
On 24/01/17(Tue) 14:43, Richard Procter wrote:
> Hi, 
> 
> PF implements six distinct TCP option parsing loops. This patch converts 
> these to one inline function in pfvar_priv.h, normalises their semantics, 
> and strips ~100 lines. 

I like it.

> I've laid out the existing semantics below. The new loop implements the 
> timestamp parser's semantics of "(s-b) (v-3) (t-a) (t-b)". As a result,
> 
> - MSS and WSCALE parsers are stricter about candidate option len.
>   - MSS normalization is more tolerant of malformed option lists.
> 
> These changes were immaterial to the live traffic I've examined (thanks to 
> Richard Cziva for help in gathering the data).

Is it possible to build regression tests for that?



Re: refactor PF option parsing loops

2017-01-24 Thread Alexandr Nedvedicky
Hello Richard,

> PF implements six distinct TCP option parsing loops. This patch converts 
> these to one inline function in pfvar_priv.h, normalises their semantics, 
> and strips ~100 lines. 

what is the reason to keep function definition in pfvar_priv.h?
I would expect to stick function header to pfvar_priv.h and
definition to .c.

The only reason, which comes to my mind you want to avoid the extra
stack frame for any price. So the only way to give compiler chance
to inline the pf_find_tcpopt() is to keep its definition in .h.
is my assumption correct?

My preference is to put the function to .c.

thanks and
regards
sasha



Re: refactor PF option parsing loops

2017-01-23 Thread Richard Procter

PS Find this patch broken down for easier review here:  

http://203.79.107.124/opts/

On Tue, 24 Jan 2017, Richard Procter wrote:

> Hi,
>
> PF implements six distinct TCP option parsing loops. This patch converts
> these to one inline function in pfvar_priv.h, normalises their semantics,
> and strips ~100 lines.




refactor PF option parsing loops

2017-01-23 Thread Richard Procter
Hi, 

PF implements six distinct TCP option parsing loops. This patch converts 
these to one inline function in pfvar_priv.h, normalises their semantics, 
and strips ~100 lines. 

I've laid out the existing semantics below. The new loop implements the 
timestamp parser's semantics of "(s-b) (v-3) (t-a) (t-b)". As a result,

- MSS and WSCALE parsers are stricter about candidate option len.
- MSS normalization is more tolerant of malformed option lists.

These changes were immaterial to the live traffic I've examined (thanks to 
Richard Cziva for help in gathering the data).

I'd like test reports before committing. 

comments, oks? 

best, 
Richard. 

* postcondition on identity (return correct option) "validity"

- 'r[]' contains the returned option.

r[0] = TYPE /\

MIN_TYPELEN >= 2 /\ 

MAX_TYPELEN  = r[1]  = MIN_TYPELEN  (v-1)  (fixed-len opt)  or
MAX_TYPELEN >= r[1] >= MIN_TYPELEN  (v-2)  (weaker) or 
   r[1] >= MIN_TYPELEN  (v-3)  (weaker) or 
   r[1] >= 2(v-4)  (weaker) or 
   true (v-5)  (weakest)


* postcondition on (eoh - opt) (ensure buffer safety) "safety"

- 'eoh' points to one past the end of option header
- 'opt' points to returned option

(eoh - opt) >= r[1] (s-a) 
(eoh - opt) >= MIN_TYPELEN  (s-b)


* parsing (tolerance of malformed headers) "tolerance"

r[0] = EOL=>   continue with r[1] := 1   (t-b)
r[1] < 2  =>   continue with r[1] := 2   (t-a)   
r[1] < 2  =>   break (t-d) 
(eoh - opt) < r[1]=>   break (t-c) 


* Analysis of existing parsers
  safety validity 
tolerance
[TS:fixed:10]  pf_norm.c:pf_normalize_tcp_init():  (s-b) (v-3) 
(t-a) (t-b)
[TS:fixed:10]  pf_norm.c:pf_normalize_tcp_stateful():  (s-b) (v-3) 
(t-a) (t-b)

[SACK:var:2 + (8*n)]   pf.c:pf_modulate_sack():  (s-a) (s-b) (v-3) 
(t-a) (t-b) 

[MSS:fixed:4]  pf_norm.c:pf_normalize_mss(): (s-a) (s-b) (v-4)  
   (t-c) (t-d)
   
[MSS:fixed:4]  pf.c:pf_get_mss():  (s-b) (v-5) 
(t-a) (t-b)   
[WSCL:fixed:3] pf.c:pf_get_wscale():   (s-b) (v-5) 
(t-a) (t-b) 


--- 

Index: net/pf_norm.c
===
--- net.orig/pf_norm.c
+++ net/pf_norm.c
@@ -901,8 +901,9 @@ pf_normalize_tcp_init(struct pf_pdesc *p
 {
struct tcphdr   *th = >hdr.tcp;
u_int32_ttsval, tsecr;
-   u_int8_t hdr[60];
-   u_int8_t*opt;
+   int  olen;
+   u_int8_t opts[MAX_TCPOPTLEN], *opt = opts;
+
 
KASSERT(src->scrub == NULL);
 
@@ -935,44 +936,28 @@ pf_normalize_tcp_init(struct pf_pdesc *p
if ((th->th_flags & TH_SYN) == 0)
return (0);
 
-   if (th->th_off > (sizeof(struct tcphdr) >> 2) && src->scrub &&
-   pf_pull_hdr(pd->m, pd->off, hdr, th->th_off << 2, NULL, NULL,
-   pd->af)) {
-   /* Diddle with TCP options */
-   int hlen;
+   if (src->scrub == NULL)
+   return (0);
 
-   opt = hdr + sizeof(struct tcphdr);
-   hlen = (th->th_off << 2) - sizeof(struct tcphdr);
-   while (hlen >= TCPOLEN_TIMESTAMP) {
-   switch (*opt) {
-   case TCPOPT_EOL:/* FALLTHROUGH */
-   case TCPOPT_NOP:
-   opt++;
-   hlen--;
-   break;
-   case TCPOPT_TIMESTAMP:
-   if (opt[1] >= TCPOLEN_TIMESTAMP) {
-   src->scrub->pfss_flags |=
-   PFSS_TIMESTAMP;
-   src->scrub->pfss_ts_mod = arc4random();
-
-   /* note PFSS_PAWS not set yet */
-   memcpy(, [2],
-   sizeof(u_int32_t));
-   memcpy(, [6],
-   sizeof(u_int32_t));
-   src->scrub->pfss_tsval0 = ntohl(tsval);
-   src->scrub->pfss_tsval = ntohl(tsval);
-   src->scrub->pfss_tsecr = ntohl(tsecr);
-   getmicrouptime(>scrub->pfss_last);
-   }
-   /* FALLTHROUGH */
-   default:
-   hlen -= MAX(opt[1], 2);
-   opt += MAX(opt[1], 2);
-