ip rule: add support for fwmark/fwmask for policy routing
This adds support for fwmark/fwmask in ip rule which is needed, for example, in OpenWrt's mwan3. Masks are supported since Linux 2.6.19. Fixes: https://bugs.busybox.net/show_bug.cgi?id=11621 Signed-off-by: Rui Salvaterra <rsalvaterra@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
		
				
					committed by
					
						
						Denys Vlasenko
					
				
			
			
				
	
			
			
			
						parent
						
							16e82c61d4
						
					
				
				
					commit
					eecd6f7a6c
				
			@@ -252,7 +252,7 @@
 | 
				
			|||||||
//usage:#define iprule_trivial_usage
 | 
					//usage:#define iprule_trivial_usage
 | 
				
			||||||
//usage:       "[list] | add|del SELECTOR ACTION"
 | 
					//usage:       "[list] | add|del SELECTOR ACTION"
 | 
				
			||||||
//usage:#define iprule_full_usage "\n\n"
 | 
					//usage:#define iprule_full_usage "\n\n"
 | 
				
			||||||
//usage:       "	SELECTOR := [from PREFIX] [to PREFIX] [tos TOS] [fwmark FWMARK]\n"
 | 
					//usage:       "	SELECTOR := [from PREFIX] [to PREFIX] [tos TOS] [fwmark FWMARK[/MASK]]\n"
 | 
				
			||||||
//usage:       "			[dev IFACE] [pref NUMBER]\n"
 | 
					//usage:       "			[dev IFACE] [pref NUMBER]\n"
 | 
				
			||||||
//usage:       "	ACTION := [table TABLE_ID] [nat ADDR]\n"
 | 
					//usage:       "	ACTION := [table TABLE_ID] [nat ADDR]\n"
 | 
				
			||||||
//usage:       "			[prohibit|reject|unreachable]\n"
 | 
					//usage:       "			[prohibit|reject|unreachable]\n"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,8 +17,10 @@
 | 
				
			|||||||
#include <arpa/inet.h>
 | 
					#include <arpa/inet.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* from <linux/fib_rules.h>: */
 | 
					/* from <linux/fib_rules.h>: */
 | 
				
			||||||
#define FRA_SUPPRESS_IFGROUP   13
 | 
					#define FRA_FWMARK		10
 | 
				
			||||||
#define FRA_SUPPRESS_PREFIXLEN 14
 | 
					#define FRA_SUPPRESS_IFGROUP	13
 | 
				
			||||||
 | 
					#define FRA_SUPPRESS_PREFIXLEN	14
 | 
				
			||||||
 | 
					#define FRA_FWMASK		16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "ip_common.h"  /* #include "libbb.h" is inside */
 | 
					#include "ip_common.h"  /* #include "libbb.h" is inside */
 | 
				
			||||||
#include "rt_names.h"
 | 
					#include "rt_names.h"
 | 
				
			||||||
@@ -117,8 +119,18 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
 | 
				
			|||||||
	if (r->rtm_tos) {
 | 
						if (r->rtm_tos) {
 | 
				
			||||||
		printf("tos %s ", rtnl_dsfield_n2a(r->rtm_tos));
 | 
							printf("tos %s ", rtnl_dsfield_n2a(r->rtm_tos));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (tb[RTA_PROTOINFO]) {
 | 
					
 | 
				
			||||||
		printf("fwmark %#x ", *(uint32_t*)RTA_DATA(tb[RTA_PROTOINFO]));
 | 
						if (tb[FRA_FWMARK] || tb[FRA_FWMASK]) {
 | 
				
			||||||
 | 
							uint32_t mark = 0, mask = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (tb[FRA_FWMARK])
 | 
				
			||||||
 | 
								mark = *(uint32_t*)RTA_DATA(tb[FRA_FWMARK]);
 | 
				
			||||||
 | 
							if (tb[FRA_FWMASK]
 | 
				
			||||||
 | 
							 && (mask = *(uint32_t*)RTA_DATA(tb[FRA_FWMASK])) != 0xFFFFFFFF
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
								printf("fwmark %#x/%#x ", mark, mask);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								printf("fwmark %#x ", mark);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (tb[RTA_IIF]) {
 | 
						if (tb[RTA_IIF]) {
 | 
				
			||||||
@@ -257,10 +269,18 @@ static int iprule_modify(int cmd, char **argv)
 | 
				
			|||||||
				invarg_1_to_2(*argv, "TOS");
 | 
									invarg_1_to_2(*argv, "TOS");
 | 
				
			||||||
			req.r.rtm_tos = tos;
 | 
								req.r.rtm_tos = tos;
 | 
				
			||||||
		} else if (key == ARG_fwmark) {
 | 
							} else if (key == ARG_fwmark) {
 | 
				
			||||||
			uint32_t fwmark;
 | 
								char *slash;
 | 
				
			||||||
 | 
								uint32_t fwmark, fwmask;
 | 
				
			||||||
			NEXT_ARG();
 | 
								NEXT_ARG();
 | 
				
			||||||
 | 
								slash = strchr(*argv, '/');
 | 
				
			||||||
 | 
								if (slash)
 | 
				
			||||||
 | 
									*slash = '\0';
 | 
				
			||||||
			fwmark = get_u32(*argv, keyword_fwmark);
 | 
								fwmark = get_u32(*argv, keyword_fwmark);
 | 
				
			||||||
			addattr32(&req.n, sizeof(req), RTA_PROTOINFO, fwmark);
 | 
								addattr32(&req.n, sizeof(req), FRA_FWMARK, fwmark);
 | 
				
			||||||
 | 
								if (slash) {
 | 
				
			||||||
 | 
									fwmask = get_u32(slash + 1, "fwmask");
 | 
				
			||||||
 | 
									addattr32(&req.n, sizeof(req), FRA_FWMASK, fwmask);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		} else if (key == ARG_realms) {
 | 
							} else if (key == ARG_realms) {
 | 
				
			||||||
			uint32_t realm;
 | 
								uint32_t realm;
 | 
				
			||||||
			NEXT_ARG();
 | 
								NEXT_ARG();
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user