@@ -1484,6 +1484,123 @@ void cmd_check_internet() {
14841484 printf ("{\n \"%s\": true,\n \"connected\": %s,\n \"ipv4\": %s,\n \"ipv6\": %s\n}\n" , KEY_SUCCESS , (v4 || v6 ) ? "true" : "false" , v4 ? "true" : "false" , v6 ? "true" : "false" );
14851485}
14861486
1487+ int cmd_flush_routes (const char * arg ) {
1488+ char arg_copy [256 ];
1489+ strncpy (arg_copy , arg , sizeof (arg_copy ) - 1 );
1490+ arg_copy [sizeof (arg_copy )- 1 ] = '\0' ;
1491+
1492+ char * iface = strtok (arg_copy , ":" );
1493+ char * fam_str = strtok (NULL , ":" );
1494+ int target_family = AF_UNSPEC ;
1495+ if (fam_str ) {
1496+ if (strcmp (fam_str , "4" ) == 0 ) target_family = AF_INET ;
1497+ else if (strcmp (fam_str , "6" ) == 0 ) target_family = AF_INET6 ;
1498+ }
1499+
1500+ if (!iface ) return 1 ;
1501+ int ifindex = if_nametoindex (iface );
1502+ if (ifindex == 0 ) {
1503+ fprintf (stderr , "Interface %s not found\n" , iface );
1504+ return 1 ;
1505+ }
1506+
1507+ int sock = open_netlink_rt ();
1508+ if (sock < 0 ) return 1 ;
1509+
1510+ struct { struct nlmsghdr nlh ; struct rtgenmsg rtg ; } req ;
1511+ memset (& req , 0 , sizeof (req ));
1512+ req .nlh .nlmsg_len = NLMSG_LENGTH (sizeof (struct rtgenmsg ));
1513+ req .nlh .nlmsg_type = RTM_GETROUTE ;
1514+ req .nlh .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP ;
1515+ req .nlh .nlmsg_seq = time (NULL );
1516+ req .rtg .rtgen_family = (target_family == AF_UNSPEC ) ? AF_UNSPEC : target_family ;
1517+ send (sock , & req , req .nlh .nlmsg_len , 0 );
1518+
1519+ #define MAX_FLUSH_ROUTES 128
1520+ struct rtmsg to_delete [MAX_FLUSH_ROUTES ];
1521+ struct rtattr * rta_dst [MAX_FLUSH_ROUTES ];
1522+ struct rtattr * rta_gw [MAX_FLUSH_ROUTES ];
1523+ struct rtattr * rta_oif [MAX_FLUSH_ROUTES ];
1524+ struct rtattr * rta_priority [MAX_FLUSH_ROUTES ];
1525+ int del_count = 0 ;
1526+
1527+ char buf [BUF_SIZE ];
1528+ int len ;
1529+ while ((len = recv (sock , buf , sizeof (buf ), 0 )) > 0 ) {
1530+ struct nlmsghdr * nh = (struct nlmsghdr * )buf ;
1531+ for (; NLMSG_OK (nh , len ); nh = NLMSG_NEXT (nh , len )) {
1532+ if (nh -> nlmsg_type == NLMSG_DONE || nh -> nlmsg_type == NLMSG_ERROR ) goto rt_dump_done ;
1533+ if (nh -> nlmsg_type == RTM_NEWROUTE ) {
1534+ struct rtmsg * rt = NLMSG_DATA (nh );
1535+ struct rtattr * tb [RTA_MAX + 1 ];
1536+ parse_rtattr (tb , RTA_MAX , RTM_RTA (rt ), nh -> nlmsg_len - NLMSG_LENGTH (sizeof (* rt )));
1537+
1538+ if (tb [RTA_OIF ] && * (int * )RTA_DATA (tb [RTA_OIF ]) == ifindex ) {
1539+ if (target_family == AF_UNSPEC || rt -> rtm_family == target_family ) {
1540+ if (del_count < MAX_FLUSH_ROUTES ) {
1541+ to_delete [del_count ] = * rt ;
1542+ rta_dst [del_count ] = NULL ;
1543+ rta_gw [del_count ] = NULL ;
1544+ rta_oif [del_count ] = NULL ;
1545+ rta_priority [del_count ] = NULL ;
1546+
1547+ if (tb [RTA_DST ]) {
1548+ int rta_len = tb [RTA_DST ]-> rta_len ;
1549+ rta_dst [del_count ] = malloc (rta_len );
1550+ if (rta_dst [del_count ]) memcpy (rta_dst [del_count ], tb [RTA_DST ], rta_len );
1551+ }
1552+ if (tb [RTA_GATEWAY ]) {
1553+ int rta_len = tb [RTA_GATEWAY ]-> rta_len ;
1554+ rta_gw [del_count ] = malloc (rta_len );
1555+ if (rta_gw [del_count ]) memcpy (rta_gw [del_count ], tb [RTA_GATEWAY ], rta_len );
1556+ }
1557+ if (tb [RTA_OIF ]) {
1558+ int rta_len = tb [RTA_OIF ]-> rta_len ;
1559+ rta_oif [del_count ] = malloc (rta_len );
1560+ if (rta_oif [del_count ]) memcpy (rta_oif [del_count ], tb [RTA_OIF ], rta_len );
1561+ }
1562+ if (tb [RTA_PRIORITY ]) {
1563+ int rta_len = tb [RTA_PRIORITY ]-> rta_len ;
1564+ rta_priority [del_count ] = malloc (rta_len );
1565+ if (rta_priority [del_count ]) memcpy (rta_priority [del_count ], tb [RTA_PRIORITY ], rta_len );
1566+ }
1567+ del_count ++ ;
1568+ }
1569+ }
1570+ }
1571+ }
1572+ }
1573+ }
1574+ rt_dump_done :
1575+
1576+ for (int i = 0 ; i < del_count ; i ++ ) {
1577+ struct {
1578+ struct nlmsghdr n ;
1579+ struct rtmsg rtm ;
1580+ char attrbuf [512 ];
1581+ } del_req ;
1582+ memset (& del_req , 0 , sizeof (del_req ));
1583+ del_req .n .nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg ));
1584+ del_req .n .nlmsg_type = RTM_DELROUTE ;
1585+ del_req .n .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK ;
1586+ del_req .n .nlmsg_seq = time (NULL ) + i ;
1587+ del_req .rtm = to_delete [i ];
1588+
1589+ if (rta_dst [i ]) { add_nl_attr (& del_req .n , sizeof (del_req ), RTA_DST , RTA_DATA (rta_dst [i ]), RTA_PAYLOAD (rta_dst [i ])); free (rta_dst [i ]); }
1590+ if (rta_gw [i ]) { add_nl_attr (& del_req .n , sizeof (del_req ), RTA_GATEWAY , RTA_DATA (rta_gw [i ]), RTA_PAYLOAD (rta_gw [i ])); free (rta_gw [i ]); }
1591+ if (rta_oif [i ]) { add_nl_attr (& del_req .n , sizeof (del_req ), RTA_OIF , RTA_DATA (rta_oif [i ]), RTA_PAYLOAD (rta_oif [i ])); free (rta_oif [i ]); }
1592+ if (rta_priority [i ]) { add_nl_attr (& del_req .n , sizeof (del_req ), RTA_PRIORITY , RTA_DATA (rta_priority [i ]), RTA_PAYLOAD (rta_priority [i ])); free (rta_priority [i ]); }
1593+
1594+ send (sock , & del_req , del_req .n .nlmsg_len , 0 );
1595+ char ackbuf [1024 ];
1596+ recv (sock , ackbuf , sizeof (ackbuf ), 0 );
1597+ }
1598+ close (sock );
1599+
1600+ printf ("{\"success\": true, \"action\": \"flush_routes\", \"iface\": \"%s\", \"count\": %d}\n" , iface , del_count );
1601+ return 0 ;
1602+ }
1603+
14871604/* --- JSON Formatting --- */
14881605
14891606void get_proxy_config (char * http , char * https , char * no_proxy ) {
@@ -2513,6 +2630,7 @@ char *g_ns_delete = NULL;
25132630char * g_ns_exec_name = NULL ;
25142631char * g_route_table = NULL ;
25152632char * g_flush_addrs = NULL ;
2633+ char * g_flush_routes = NULL ;
25162634
25172635int main (int argc , char * argv []) {
25182636 atexit (cleanup_ifaces );
@@ -2541,6 +2659,7 @@ int main(int argc, char *argv[]) {
25412659 {"nullify-xdp" , required_argument , 0 , 'X' },
25422660 {"encode-ssid" , required_argument , 0 , 'E' },
25432661 {"flush-addrs" , required_argument , 0 , 'F' },
2662+ {"flush-routes" , required_argument , 0 , 'R' },
25442663 {"ns-create" , required_argument , 0 , 1001 },
25452664 {"ns-delete" , required_argument , 0 , 1002 },
25462665 {"ns-list" , no_argument , 0 , 1003 },
@@ -2551,10 +2670,10 @@ int main(int argc, char *argv[]) {
25512670 };
25522671
25532672 int opt , option_index = 0 ;
2554- while ((opt = getopt_long (argc , argv , "vhHtdLcrC:i:g:W:P:T:A:l:M:S:N:X:E:F:" , long_options , & option_index )) != -1 ) {
2673+ while ((opt = getopt_long (argc , argv , "vhHtdLcrC:i:g:W:P:T:A:l:M:S:N:X:E:F:R: " , long_options , & option_index )) != -1 ) {
25552674 switch (opt ) {
25562675 case 'v' : cmd_version (); return 0 ;
2557- case 'h' : printf ("Usage: rxnm-agent [options]\n--dump Full JSON status\n--ns-create <name> Create namespace\n--route-dump <table_id> Dump routing table\n--nullify-xdp <iface>\n--flush-addrs <iface>[:family]\n" ); return 0 ;
2676+ case 'h' : printf ("Usage: rxnm-agent [options]\n--dump Full JSON status\n--ns-create <name> Create namespace\n--route-dump <table_id> Dump routing table\n--nullify-xdp <iface>\n--flush-addrs <iface>[:family]\n--flush-routes <iface>[:family]\n " ); return 0 ;
25582677 case 'H' : cmd_health (); return 0 ;
25592678 case 't' : cmd_time (); return 0 ;
25602679 case 'L' : cmd_is_low_power (); return 0 ;
@@ -2575,6 +2694,7 @@ int main(int argc, char *argv[]) {
25752694 case 'X' : g_nullify_xdp_iface = optarg ; break ;
25762695 case 'E' : cmd_encode_ssid (optarg ); return 0 ;
25772696 case 'F' : g_flush_addrs = optarg ; break ;
2697+ case 'R' : g_flush_routes = optarg ; break ;
25782698 case 1001 : g_ns_create = optarg ; break ;
25792699 case 1002 : g_ns_delete = optarg ; break ;
25802700 case 1003 : cmd_ns_list (); return 0 ;
@@ -2614,6 +2734,7 @@ int main(int argc, char *argv[]) {
26142734 }
26152735
26162736 if (g_flush_addrs ) { return cmd_flush_addrs (g_flush_addrs ); }
2737+ if (g_flush_routes ) { return cmd_flush_routes (g_flush_routes ); }
26172738 if (g_atomic_path ) { return cmd_atomic_write (g_atomic_path , g_perm_str ); }
26182739 if (g_append_path && g_append_line ) { return cmd_append_config (g_append_path , g_append_line ); }
26192740 if (g_monitor_iface ) { cmd_monitor_roam (g_monitor_iface , g_monitor_thresh ); return 0 ; }
0 commit comments