@@ -224,11 +224,6 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_krule *r,
224224 if (pf_map_addr (af , r , saddr , naddr , & init_addr , sn ))
225225 return (1 );
226226
227- if (proto == IPPROTO_ICMP ) {
228- low = 1 ;
229- high = 65535 ;
230- }
231-
232227 bzero (& key , sizeof (key ));
233228 key .af = af ;
234229 key .proto = proto ;
@@ -310,6 +305,42 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_krule *r,
310305 return (1 ); /* none available */
311306}
312307
308+ static int
309+ pf_get_mape_sport (sa_family_t af , u_int8_t proto , struct pf_krule * r ,
310+ struct pf_addr * saddr , uint16_t sport , struct pf_addr * daddr ,
311+ uint16_t dport , struct pf_addr * naddr , uint16_t * nport ,
312+ struct pf_ksrc_node * * sn )
313+ {
314+ uint16_t psmask , low , highmask ;
315+ uint16_t i , ahigh , cut ;
316+ int ashift , psidshift ;
317+
318+ ashift = 16 - r -> rpool .mape .offset ;
319+ psidshift = ashift - r -> rpool .mape .psidlen ;
320+ psmask = r -> rpool .mape .psid & ((1U << r -> rpool .mape .psidlen ) - 1 );
321+ psmask = psmask << psidshift ;
322+ highmask = (1U << psidshift ) - 1 ;
323+
324+ ahigh = (1U << r -> rpool .mape .offset ) - 1 ;
325+ cut = arc4random () & ahigh ;
326+ if (cut == 0 )
327+ cut = 1 ;
328+
329+ for (i = cut ; i <= ahigh ; i ++ ) {
330+ low = (i << ashift ) | psmask ;
331+ if (!pf_get_sport (af , proto , r , saddr , sport , daddr , dport ,
332+ naddr , nport , low , low | highmask , sn ))
333+ return (0 );
334+ }
335+ for (i = cut - 1 ; i > 0 ; i -- ) {
336+ low = (i << ashift ) | psmask ;
337+ if (!pf_get_sport (af , proto , r , saddr , sport , daddr , dport ,
338+ naddr , nport , low , low | highmask , sn ))
339+ return (0 );
340+ }
341+ return (1 );
342+ }
343+
313344int
314345pf_map_addr (sa_family_t af , struct pf_krule * r , struct pf_addr * saddr ,
315346 struct pf_addr * naddr , struct pf_addr * init_addr , struct pf_ksrc_node * * sn )
@@ -530,6 +561,7 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
530561 struct pf_krule * r = NULL ;
531562 struct pf_addr * naddr ;
532563 uint16_t * nport ;
564+ uint16_t low , high ;
533565
534566 PF_RULES_RASSERT ();
535567 KASSERT (* skp == NULL , ("*skp not NULL" ));
@@ -577,9 +609,26 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
577609
578610 switch (r -> action ) {
579611 case PF_NAT :
580- if (pf_get_sport (pd -> af , pd -> proto , r , saddr , sport , daddr ,
581- dport , naddr , nport , r -> rpool .proxy_port [0 ],
582- r -> rpool .proxy_port [1 ], sn )) {
612+ if (pd -> proto == IPPROTO_ICMP ) {
613+ low = 1 ;
614+ high = 65535 ;
615+ } else {
616+ low = r -> rpool .proxy_port [0 ];
617+ high = r -> rpool .proxy_port [1 ];
618+ }
619+ if (r -> rpool .mape .offset > 0 ) {
620+ if (pf_get_mape_sport (pd -> af , pd -> proto , r , saddr ,
621+ sport , daddr , dport , naddr , nport , sn )) {
622+ DPFPRINTF (PF_DEBUG_MISC ,
623+ ("pf: MAP-E port allocation (%u/%u/%u)"
624+ " failed\n" ,
625+ r -> rpool .mape .offset ,
626+ r -> rpool .mape .psidlen ,
627+ r -> rpool .mape .psid ));
628+ goto notrans ;
629+ }
630+ } else if (pf_get_sport (pd -> af , pd -> proto , r , saddr , sport ,
631+ daddr , dport , naddr , nport , low , high , sn )) {
583632 DPFPRINTF (PF_DEBUG_MISC ,
584633 ("pf: NAT proxy port allocation (%u-%u) failed\n" ,
585634 r -> rpool .proxy_port [0 ], r -> rpool .proxy_port [1 ]));
0 commit comments