@@ -83,6 +83,7 @@ int pfctl_clear_iface_states(int, const char *, int);
83
83
void pfctl_addrprefix (char * , struct pf_addr * );
84
84
int pfctl_kill_src_nodes (int , const char * , int );
85
85
int pfctl_net_kill_states (int , const char * , int );
86
+ int pfctl_gateway_kill_states (int , const char * , int );
86
87
int pfctl_label_kill_states (int , const char * , int );
87
88
int pfctl_id_kill_states (int , const char * , int );
88
89
void pfctl_init_options (struct pfctl * );
@@ -246,7 +247,7 @@ usage(void)
246
247
fprintf (stderr ,
247
248
"usage: %s [-AdeghmNnOPqRrvz] [-a anchor] [-D macro=value] [-F modifier]\n"
248
249
"\t[-f file] [-i interface] [-K host | network]\n"
249
- "\t[-k host | network | label | id] [-o level] [-p device]\n"
250
+ "\t[-k host | network | gateway | label | id] [-o level] [-p device]\n"
250
251
"\t[-s modifier] [-t table -T command [address ...]] [-x level]\n" ,
251
252
__progname );
252
253
@@ -744,6 +745,67 @@ pfctl_net_kill_states(int dev, const char *iface, int opts)
744
745
return (0 );
745
746
}
746
747
748
+ int
749
+ pfctl_gateway_kill_states (int dev , const char * iface , int opts )
750
+ {
751
+ struct pfctl_kill kill ;
752
+ struct addrinfo * res , * resp ;
753
+ struct sockaddr last_src ;
754
+ unsigned int newkilled ;
755
+ int killed = 0 ;
756
+ int ret_ga ;
757
+
758
+ if (state_killers != 2 || (strlen (state_kill [1 ]) == 0 )) {
759
+ warnx ("no gateway specified" );
760
+ usage ();
761
+ }
762
+
763
+ memset (& kill , 0 , sizeof (kill ));
764
+ memset (& kill .rt_addr .addr .v .a .mask , 0xff ,
765
+ sizeof (kill .rt_addr .addr .v .a .mask ));
766
+ memset (& last_src , 0xff , sizeof (last_src ));
767
+ if (iface != NULL && strlcpy (kill .ifname , iface ,
768
+ sizeof (kill .ifname )) >= sizeof (kill .ifname ))
769
+ errx (1 , "invalid interface: %s" , iface );
770
+
771
+ pfctl_addrprefix (state_kill [1 ], & kill .rt_addr .addr .v .a .mask );
772
+
773
+ if ((ret_ga = getaddrinfo (state_kill [1 ], NULL , NULL , & res ))) {
774
+ errx (1 , "getaddrinfo: %s" , gai_strerror (ret_ga ));
775
+ /* NOTREACHED */
776
+ }
777
+ for (resp = res ; resp ; resp = resp -> ai_next ) {
778
+ if (resp -> ai_addr == NULL )
779
+ continue ;
780
+ /* We get lots of duplicates. Catch the easy ones */
781
+ if (memcmp (& last_src , resp -> ai_addr , sizeof (last_src )) == 0 )
782
+ continue ;
783
+ last_src = * (struct sockaddr * )resp -> ai_addr ;
784
+
785
+ kill .af = resp -> ai_family ;
786
+
787
+ if (kill .af == AF_INET )
788
+ kill .rt_addr .addr .v .a .addr .v4 =
789
+ ((struct sockaddr_in * )resp -> ai_addr )-> sin_addr ;
790
+ else if (kill .af == AF_INET6 )
791
+ kill .rt_addr .addr .v .a .addr .v6 =
792
+ ((struct sockaddr_in6 * )resp -> ai_addr )->
793
+ sin6_addr ;
794
+ else
795
+ errx (1 , "Unknown address family %d" , kill .af );
796
+
797
+ if (pfctl_kill_states (dev , & kill , & newkilled ))
798
+ err (1 , "DIOCKILLSTATES" );
799
+ killed += newkilled ;
800
+ }
801
+
802
+ freeaddrinfo (res );
803
+
804
+ if ((opts & PF_OPT_QUIET ) == 0 )
805
+ fprintf (stderr , "killed %d states\n" , killed );
806
+ return (0 );
807
+ }
808
+
747
809
int
748
810
pfctl_label_kill_states (int dev , const char * iface , int opts )
749
811
{
@@ -2455,6 +2517,8 @@ main(int argc, char *argv[])
2455
2517
pfctl_label_kill_states (dev , ifaceopt , opts );
2456
2518
else if (!strcmp (state_kill [0 ], "id" ))
2457
2519
pfctl_id_kill_states (dev , ifaceopt , opts );
2520
+ else if (!strcmp (state_kill [0 ], "gateway" ))
2521
+ pfctl_gateway_kill_states (dev , ifaceopt , opts );
2458
2522
else
2459
2523
pfctl_net_kill_states (dev , ifaceopt , opts );
2460
2524
}
0 commit comments