144d362409d5469aed47d19e7908d19bd194493aThomas Graf/* 244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/route/rule.c Routing Rules 344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 444d362409d5469aed47d19e7908d19bd194493aThomas Graf * This library is free software; you can redistribute it and/or 544d362409d5469aed47d19e7908d19bd194493aThomas Graf * modify it under the terms of the GNU Lesser General Public 644d362409d5469aed47d19e7908d19bd194493aThomas Graf * License as published by the Free Software Foundation version 2.1 744d362409d5469aed47d19e7908d19bd194493aThomas Graf * of the License. 844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 9054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch> 1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1144d362409d5469aed47d19e7908d19bd194493aThomas Graf 1244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @ingroup rtnl 1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup rule Routing Rules 1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @brief 1644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 1744d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1844d362409d5469aed47d19e7908d19bd194493aThomas Graf 19054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#include <netlink-private/netlink.h> 2044d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h> 2144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h> 2244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/rtnl.h> 2344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/rule.h> 2444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <inttypes.h> 2544d362409d5469aed47d19e7908d19bd194493aThomas Graf 2644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @cond SKIP */ 2744d362409d5469aed47d19e7908d19bd194493aThomas Graf#define RULE_ATTR_FAMILY 0x0001 28054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_TABLE 0x0002 29054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_ACTION 0x0004 30054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_FLAGS 0x0008 31054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_IIFNAME 0x0010 32054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_OIFNAME 0x0020 33054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_PRIO 0x0040 34054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_MARK 0x0080 35054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_MASK 0x0100 36054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_GOTO 0x0200 37054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_SRC 0x0400 38054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_DST 0x0800 39054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_DSFIELD 0x1000 40054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_FLOW 0x2000 4144d362409d5469aed47d19e7908d19bd194493aThomas Graf 4244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_cache_ops rtnl_rule_ops; 4344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_object_ops rule_obj_ops; 4444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @endcond */ 4544d362409d5469aed47d19e7908d19bd194493aThomas Graf 4644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void rule_free_data(struct nl_object *c) 4744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 4844d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_rule *rule = nl_object_priv(c); 4944d362409d5469aed47d19e7908d19bd194493aThomas Graf 5044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!rule) 5144d362409d5469aed47d19e7908d19bd194493aThomas Graf return; 5244d362409d5469aed47d19e7908d19bd194493aThomas Graf 5344d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_put(rule->r_src); 5444d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_put(rule->r_dst); 5544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 5644d362409d5469aed47d19e7908d19bd194493aThomas Graf 5744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int rule_clone(struct nl_object *_dst, struct nl_object *_src) 5844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 5944d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_rule *dst = nl_object_priv(_dst); 6044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_rule *src = nl_object_priv(_src); 6144d362409d5469aed47d19e7908d19bd194493aThomas Graf 6244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (src->r_src) 6344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!(dst->r_src = nl_addr_clone(src->r_src))) 648a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 6544d362409d5469aed47d19e7908d19bd194493aThomas Graf 6644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (src->r_dst) 6744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!(dst->r_dst = nl_addr_clone(src->r_dst))) 688a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 6944d362409d5469aed47d19e7908d19bd194493aThomas Graf 7044d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 7144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 7244d362409d5469aed47d19e7908d19bd194493aThomas Graf 73054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartstatic struct nla_policy rule_policy[FRA_MAX+1] = { 74054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart [FRA_TABLE] = { .type = NLA_U32 }, 75054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart [FRA_IIFNAME] = { .type = NLA_STRING, .maxlen = IFNAMSIZ }, 76054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart [FRA_OIFNAME] = { .type = NLA_STRING, .maxlen = IFNAMSIZ }, 77054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart [FRA_PRIORITY] = { .type = NLA_U32 }, 78054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart [FRA_FWMARK] = { .type = NLA_U32 }, 79054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart [FRA_FWMASK] = { .type = NLA_U32 }, 80054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart [FRA_GOTO] = { .type = NLA_U32 }, 81054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart [FRA_FLOW] = { .type = NLA_U32 }, 8244d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 8344d362409d5469aed47d19e7908d19bd194493aThomas Graf 8444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, 853040a1d6254465bed9e44e4d1bf279c2c50cd16aThomas Graf struct nlmsghdr *n, struct nl_parser_param *pp) 8644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 8744d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_rule *rule; 88054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart struct fib_rule_hdr *frh; 89054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart struct nlattr *tb[FRA_MAX+1]; 90eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf int err = 1, family; 9144d362409d5469aed47d19e7908d19bd194493aThomas Graf 9244d362409d5469aed47d19e7908d19bd194493aThomas Graf rule = rtnl_rule_alloc(); 9344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!rule) { 948a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_NOMEM; 9544d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 9644d362409d5469aed47d19e7908d19bd194493aThomas Graf } 9744d362409d5469aed47d19e7908d19bd194493aThomas Graf 9844d362409d5469aed47d19e7908d19bd194493aThomas Graf rule->ce_msgtype = n->nlmsg_type; 99054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart frh = nlmsg_data(n); 10044d362409d5469aed47d19e7908d19bd194493aThomas Graf 101054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart err = nlmsg_parse(n, sizeof(*frh), tb, FRA_MAX, rule_policy); 10244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 10344d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 10444d362409d5469aed47d19e7908d19bd194493aThomas Graf 105054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->r_family = family = frh->family; 106054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->r_table = frh->table; 107054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->r_action = frh->action; 108054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->r_flags = frh->flags; 109054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 110054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_TABLE | RULE_ATTR_ACTION | 111054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart RULE_ATTR_FLAGS); 112054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 113054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart /* ipv4 only */ 114054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (frh->tos) { 115054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->r_dsfield = frh->tos; 116054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->ce_mask |= RULE_ATTR_DSFIELD; 11744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 11844d362409d5469aed47d19e7908d19bd194493aThomas Graf 119054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (tb[FRA_TABLE]) { 120054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->r_table = nla_get_u32(tb[FRA_TABLE]); 121054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->ce_mask |= RULE_ATTR_TABLE; 12244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 12344d362409d5469aed47d19e7908d19bd194493aThomas Graf 124054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (tb[FRA_IIFNAME]) { 125054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart nla_strlcpy(rule->r_iifname, tb[FRA_IIFNAME], IFNAMSIZ); 126054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->ce_mask |= RULE_ATTR_IIFNAME; 12744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 12844d362409d5469aed47d19e7908d19bd194493aThomas Graf 129054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (tb[FRA_OIFNAME]) { 130054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart nla_strlcpy(rule->r_oifname, tb[FRA_OIFNAME], IFNAMSIZ); 131054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->ce_mask |= RULE_ATTR_OIFNAME; 132054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart } 133054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 134054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (tb[FRA_PRIORITY]) { 135054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->r_prio = nla_get_u32(tb[FRA_PRIORITY]); 136054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->ce_mask |= RULE_ATTR_PRIO; 137054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart } 138054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 139054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (tb[FRA_FWMARK]) { 140054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->r_mark = nla_get_u32(tb[FRA_FWMARK]); 14144d362409d5469aed47d19e7908d19bd194493aThomas Graf rule->ce_mask |= RULE_ATTR_MARK; 14244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 14344d362409d5469aed47d19e7908d19bd194493aThomas Graf 144054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (tb[FRA_FWMASK]) { 145054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->r_mask = nla_get_u32(tb[FRA_FWMASK]); 146054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->ce_mask |= RULE_ATTR_MASK; 147054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart } 148054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 149054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (tb[FRA_GOTO]) { 150054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->r_goto = nla_get_u32(tb[FRA_GOTO]); 151054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->ce_mask |= RULE_ATTR_GOTO; 15244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 15344d362409d5469aed47d19e7908d19bd194493aThomas Graf 154054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (tb[FRA_SRC]) { 155054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (!(rule->r_src = nl_addr_alloc_attr(tb[FRA_SRC], family))) 156054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart goto errout_enomem; 157054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 158054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart nl_addr_set_prefixlen(rule->r_src, frh->src_len); 159054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->ce_mask |= RULE_ATTR_SRC; 16044d362409d5469aed47d19e7908d19bd194493aThomas Graf } 16144d362409d5469aed47d19e7908d19bd194493aThomas Graf 162054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (tb[FRA_DST]) { 163054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (!(rule->r_dst = nl_addr_alloc_attr(tb[FRA_DST], family))) 164eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf goto errout_enomem; 165054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart nl_addr_set_prefixlen(rule->r_dst, frh->dst_len); 166054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->ce_mask |= RULE_ATTR_DST; 16744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 16844d362409d5469aed47d19e7908d19bd194493aThomas Graf 169054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart /* ipv4 only */ 170054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (tb[FRA_FLOW]) { 171054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->r_flow = nla_get_u32(tb[FRA_FLOW]); 172054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->ce_mask |= RULE_ATTR_FLOW; 173054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart } 174107dc162c56ace6eea5a167b7881520e6cecb831Ben Gamsa 17544d362409d5469aed47d19e7908d19bd194493aThomas Graf err = pp->pp_cb((struct nl_object *) rule, pp); 17644d362409d5469aed47d19e7908d19bd194493aThomas Graferrout: 17744d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_rule_put(rule); 17844d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 179eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf 180eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graferrout_enomem: 181eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf err = -NLE_NOMEM; 182eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf goto errout; 18344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 18444d362409d5469aed47d19e7908d19bd194493aThomas Graf 1851155370f520cb64657e25153255cf7dc1424317fThomas Grafstatic int rule_request_update(struct nl_cache *c, struct nl_sock *h) 18644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 18744d362409d5469aed47d19e7908d19bd194493aThomas Graf return nl_rtgen_request(h, RTM_GETRULE, AF_UNSPEC, NLM_F_DUMP); 18844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 18944d362409d5469aed47d19e7908d19bd194493aThomas Graf 190d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void rule_dump_line(struct nl_object *o, struct nl_dump_params *p) 19144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 19244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_rule *r = (struct rtnl_rule *) o; 19344d362409d5469aed47d19e7908d19bd194493aThomas Graf char buf[128]; 19444d362409d5469aed47d19e7908d19bd194493aThomas Graf 195d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, "%8d ", (r->ce_mask & RULE_ATTR_PRIO) ? r->r_prio : 0); 196d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "%s ", nl_af2str(r->r_family, buf, sizeof(buf))); 19744d362409d5469aed47d19e7908d19bd194493aThomas Graf 19844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (r->ce_mask & RULE_ATTR_SRC) 199d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "from %s ", 20044d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr2str(r->r_src, buf, sizeof(buf))); 20144d362409d5469aed47d19e7908d19bd194493aThomas Graf 20244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (r->ce_mask & RULE_ATTR_DST) 203d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "to %s ", 20444d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr2str(r->r_dst, buf, sizeof(buf))); 20544d362409d5469aed47d19e7908d19bd194493aThomas Graf 206054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (r->ce_mask & RULE_ATTR_DSFIELD) 207054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart nl_dump(p, "tos %u ", r->r_dsfield); 208054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 209054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (r->ce_mask & (RULE_ATTR_MARK | RULE_ATTR_MASK)) 210054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart nl_dump(p, "mark %#x/%#x", r->r_mark, r->r_mask); 21144d362409d5469aed47d19e7908d19bd194493aThomas Graf 212054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (r->ce_mask & RULE_ATTR_IIFNAME) 213054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart nl_dump(p, "iif %s ", r->r_iifname); 21444d362409d5469aed47d19e7908d19bd194493aThomas Graf 215054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (r->ce_mask & RULE_ATTR_OIFNAME) 216054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart nl_dump(p, "oif %s ", r->r_oifname); 21744d362409d5469aed47d19e7908d19bd194493aThomas Graf 21844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (r->ce_mask & RULE_ATTR_TABLE) 219d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "lookup %s ", 22044d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_route_table2str(r->r_table, buf, sizeof(buf))); 22144d362409d5469aed47d19e7908d19bd194493aThomas Graf 222054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (r->ce_mask & RULE_ATTR_FLOW) 223054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart nl_dump(p, "flow %s ", 224054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rtnl_realms2str(r->r_flow, buf, sizeof(buf))); 22544d362409d5469aed47d19e7908d19bd194493aThomas Graf 226054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (r->ce_mask & RULE_ATTR_GOTO) 227054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart nl_dump(p, "goto %u ", r->r_goto); 228054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 229054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (r->ce_mask & RULE_ATTR_ACTION) 230054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart nl_dump(p, "action %s", 231054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart nl_rtntype2str(r->r_action, buf, sizeof(buf))); 232054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 233054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart nl_dump(p, "\n"); 23444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 23544d362409d5469aed47d19e7908d19bd194493aThomas Graf 236d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void rule_dump_details(struct nl_object *obj, struct nl_dump_params *p) 23744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 238d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf rule_dump_line(obj, p); 23944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 24044d362409d5469aed47d19e7908d19bd194493aThomas Graf 241d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void rule_dump_stats(struct nl_object *obj, struct nl_dump_params *p) 24244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 243d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf rule_dump_details(obj, p); 24444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 24544d362409d5469aed47d19e7908d19bd194493aThomas Graf 246054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_FLAGS 0x0008 24744d362409d5469aed47d19e7908d19bd194493aThomas Graf 24844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int rule_compare(struct nl_object *_a, struct nl_object *_b, 24944d362409d5469aed47d19e7908d19bd194493aThomas Graf uint32_t attrs, int flags) 25044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 25144d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_rule *a = (struct rtnl_rule *) _a; 25244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_rule *b = (struct rtnl_rule *) _b; 25344d362409d5469aed47d19e7908d19bd194493aThomas Graf int diff = 0; 25444d362409d5469aed47d19e7908d19bd194493aThomas Graf 25544d362409d5469aed47d19e7908d19bd194493aThomas Graf#define RULE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, RULE_ATTR_##ATTR, a, b, EXPR) 25644d362409d5469aed47d19e7908d19bd194493aThomas Graf 25744d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= RULE_DIFF(FAMILY, a->r_family != b->r_family); 25844d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= RULE_DIFF(TABLE, a->r_table != b->r_table); 259054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart diff |= RULE_DIFF(ACTION, a->r_action != b->r_action); 260054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart diff |= RULE_DIFF(IIFNAME, strcmp(a->r_iifname, b->r_iifname)); 261054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart diff |= RULE_DIFF(OIFNAME, strcmp(a->r_oifname, b->r_oifname)); 26244d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= RULE_DIFF(PRIO, a->r_prio != b->r_prio); 26344d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= RULE_DIFF(MARK, a->r_mark != b->r_mark); 264054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart diff |= RULE_DIFF(MASK, a->r_mask != b->r_mask); 265054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart diff |= RULE_DIFF(GOTO, a->r_goto != b->r_goto); 26644d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= RULE_DIFF(SRC, nl_addr_cmp(a->r_src, b->r_src)); 26744d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= RULE_DIFF(DST, nl_addr_cmp(a->r_dst, b->r_dst)); 268054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart diff |= RULE_DIFF(DSFIELD, a->r_dsfield != b->r_dsfield); 269054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart diff |= RULE_DIFF(FLOW, a->r_flow != b->r_flow); 27044d362409d5469aed47d19e7908d19bd194493aThomas Graf 27144d362409d5469aed47d19e7908d19bd194493aThomas Graf#undef RULE_DIFF 27244d362409d5469aed47d19e7908d19bd194493aThomas Graf 27344d362409d5469aed47d19e7908d19bd194493aThomas Graf return diff; 27444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 27544d362409d5469aed47d19e7908d19bd194493aThomas Graf 276054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartstatic const struct trans_tbl rule_attrs[] = { 27744d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(RULE_ATTR_FAMILY, family) 278054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart __ADD(RULE_ATTR_TABLE, table) 279054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart __ADD(RULE_ATTR_ACTION, action) 280054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart __ADD(RULE_ATTR_IIFNAME, iifname) 281054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart __ADD(RULE_ATTR_OIFNAME, oifname) 28244d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(RULE_ATTR_PRIO, prio) 28344d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(RULE_ATTR_MARK, mark) 284054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart __ADD(RULE_ATTR_MASK, mask) 285054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart __ADD(RULE_ATTR_GOTO, goto) 28644d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(RULE_ATTR_SRC, src) 28744d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(RULE_ATTR_DST, dst) 28844d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(RULE_ATTR_DSFIELD, dsfield) 289054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart __ADD(RULE_ATTR_FLOW, flow) 29044d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 29144d362409d5469aed47d19e7908d19bd194493aThomas Graf 29244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic char *rule_attrs2str(int attrs, char *buf, size_t len) 29344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 29444d362409d5469aed47d19e7908d19bd194493aThomas Graf return __flags2str(attrs, buf, len, rule_attrs, 29544d362409d5469aed47d19e7908d19bd194493aThomas Graf ARRAY_SIZE(rule_attrs)); 29644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 29744d362409d5469aed47d19e7908d19bd194493aThomas Graf 29844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 29944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Allocation/Freeing 30044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 30144d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 30244d362409d5469aed47d19e7908d19bd194493aThomas Graf 30344d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct rtnl_rule *rtnl_rule_alloc(void) 30444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 30544d362409d5469aed47d19e7908d19bd194493aThomas Graf return (struct rtnl_rule *) nl_object_alloc(&rule_obj_ops); 30644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 30744d362409d5469aed47d19e7908d19bd194493aThomas Graf 30844d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_rule_put(struct rtnl_rule *rule) 30944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 31044d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_object_put((struct nl_object *) rule); 31144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 31244d362409d5469aed47d19e7908d19bd194493aThomas Graf 31344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 31444d362409d5469aed47d19e7908d19bd194493aThomas Graf 31544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 31644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Cache Management 31744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 31844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 31944d362409d5469aed47d19e7908d19bd194493aThomas Graf 32044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 3218a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Build a rule cache including all rules currently configured in the kernel. 322054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg sock Netlink socket. 3238a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @arg family Address family or AF_UNSPEC. 3248a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @arg result Pointer to store resulting cache. 32544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 32644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Allocates a new rule cache, initializes it properly and updates it 3278a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * to include all rules currently configured in the kernel. 32844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 3298a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @return 0 on success or a negative error code. 33044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 3311155370f520cb64657e25153255cf7dc1424317fThomas Grafint rtnl_rule_alloc_cache(struct nl_sock *sock, int family, 3328a3efffa5b3fde252675239914118664d36a2c24Thomas Graf struct nl_cache **result) 33344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 33444d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_cache * cache; 3358a3efffa5b3fde252675239914118664d36a2c24Thomas Graf int err; 33644d362409d5469aed47d19e7908d19bd194493aThomas Graf 3378a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if (!(cache = nl_cache_alloc(&rtnl_rule_ops))) 3388a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 33944d362409d5469aed47d19e7908d19bd194493aThomas Graf 3408a3efffa5b3fde252675239914118664d36a2c24Thomas Graf cache->c_iarg1 = family; 34144d362409d5469aed47d19e7908d19bd194493aThomas Graf 3428a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if (sock && (err = nl_cache_refill(sock, cache)) < 0) { 34344d362409d5469aed47d19e7908d19bd194493aThomas Graf free(cache); 3448a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return err; 34544d362409d5469aed47d19e7908d19bd194493aThomas Graf } 34644d362409d5469aed47d19e7908d19bd194493aThomas Graf 3478a3efffa5b3fde252675239914118664d36a2c24Thomas Graf *result = cache; 3488a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return 0; 34944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 35044d362409d5469aed47d19e7908d19bd194493aThomas Graf 35144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 35244d362409d5469aed47d19e7908d19bd194493aThomas Graf 35344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 35444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Rule Addition 35544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 35644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 35744d362409d5469aed47d19e7908d19bd194493aThomas Graf 3588a3efffa5b3fde252675239914118664d36a2c24Thomas Grafstatic int build_rule_msg(struct rtnl_rule *tmpl, int cmd, int flags, 3598a3efffa5b3fde252675239914118664d36a2c24Thomas Graf struct nl_msg **result) 36044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 36144d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_msg *msg; 362054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart struct fib_rule_hdr frh = { 363054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart .family = tmpl->r_family, 364054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart .table = tmpl->r_table, 365054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart .action = tmpl->r_action, 366054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart .flags = tmpl->r_flags, 367054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart .tos = tmpl->r_dsfield, 36844d362409d5469aed47d19e7908d19bd194493aThomas Graf }; 36944d362409d5469aed47d19e7908d19bd194493aThomas Graf 370054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (!(tmpl->ce_mask & RULE_ATTR_FAMILY)) 371054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return -NLE_MISSING_ATTR; 37244d362409d5469aed47d19e7908d19bd194493aThomas Graf 37344d362409d5469aed47d19e7908d19bd194493aThomas Graf msg = nlmsg_alloc_simple(cmd, flags); 37444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!msg) 3758a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 37644d362409d5469aed47d19e7908d19bd194493aThomas Graf 377054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (tmpl->ce_mask & RULE_ATTR_SRC) 378054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart frh.src_len = nl_addr_get_prefixlen(tmpl->r_src); 379054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 380054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (tmpl->ce_mask & RULE_ATTR_DST) 381054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart frh.dst_len = nl_addr_get_prefixlen(tmpl->r_dst); 382054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 383054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (nlmsg_append(msg, &frh, sizeof(frh), NLMSG_ALIGNTO) < 0) 38444d362409d5469aed47d19e7908d19bd194493aThomas Graf goto nla_put_failure; 38544d362409d5469aed47d19e7908d19bd194493aThomas Graf 386054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart /* Additional table attribute replacing the 8bit in the header, was 387054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * required to allow more than 256 tables. */ 388054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart NLA_PUT_U32(msg, FRA_TABLE, tmpl->r_table); 389054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 39044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tmpl->ce_mask & RULE_ATTR_SRC) 391054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart NLA_PUT_ADDR(msg, FRA_SRC, tmpl->r_src); 39244d362409d5469aed47d19e7908d19bd194493aThomas Graf 393054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (tmpl->ce_mask & RULE_ATTR_DST) 394054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart NLA_PUT_ADDR(msg, FRA_DST, tmpl->r_dst); 395054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 396054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (tmpl->ce_mask & RULE_ATTR_IIFNAME) 397054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart NLA_PUT_STRING(msg, FRA_IIFNAME, tmpl->r_iifname); 398054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 399054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (tmpl->ce_mask & RULE_ATTR_OIFNAME) 400054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart NLA_PUT_STRING(msg, FRA_OIFNAME, tmpl->r_oifname); 40144d362409d5469aed47d19e7908d19bd194493aThomas Graf 40244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tmpl->ce_mask & RULE_ATTR_PRIO) 403054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart NLA_PUT_U32(msg, FRA_PRIORITY, tmpl->r_prio); 40444d362409d5469aed47d19e7908d19bd194493aThomas Graf 40544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tmpl->ce_mask & RULE_ATTR_MARK) 406054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart NLA_PUT_U32(msg, FRA_FWMARK, tmpl->r_mark); 407054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 408054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (tmpl->ce_mask & RULE_ATTR_MASK) 409054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart NLA_PUT_U32(msg, FRA_FWMASK, tmpl->r_mask); 410054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 411054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (tmpl->ce_mask & RULE_ATTR_GOTO) 412054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart NLA_PUT_U32(msg, FRA_GOTO, tmpl->r_goto); 41344d362409d5469aed47d19e7908d19bd194493aThomas Graf 414054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (tmpl->ce_mask & RULE_ATTR_FLOW) 415054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart NLA_PUT_U32(msg, FRA_FLOW, tmpl->r_flow); 41644d362409d5469aed47d19e7908d19bd194493aThomas Graf 41744d362409d5469aed47d19e7908d19bd194493aThomas Graf 4188a3efffa5b3fde252675239914118664d36a2c24Thomas Graf *result = msg; 4198a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return 0; 42044d362409d5469aed47d19e7908d19bd194493aThomas Graf 42144d362409d5469aed47d19e7908d19bd194493aThomas Grafnla_put_failure: 42244d362409d5469aed47d19e7908d19bd194493aThomas Graf nlmsg_free(msg); 4238a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_MSGSIZE; 42444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 42544d362409d5469aed47d19e7908d19bd194493aThomas Graf 42644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 42744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Build netlink request message to add a new rule 42844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg tmpl template with data of new rule 42944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags additional netlink message flags 430054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg result Result pointer 43144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 43244d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a new netlink message requesting a addition of a new 43344d362409d5469aed47d19e7908d19bd194493aThomas Graf * rule. The netlink message header isn't fully equipped with 43444d362409d5469aed47d19e7908d19bd194493aThomas Graf * all relevant fields and must thus be sent out via nl_send_auto_complete() 43544d362409d5469aed47d19e7908d19bd194493aThomas Graf * or supplemented as needed. \a tmpl must contain the attributes of the new 43644d362409d5469aed47d19e7908d19bd194493aThomas Graf * address set via \c rtnl_rule_set_* functions. 43744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 438054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return 0 on success or a negative error code. 43944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 4408a3efffa5b3fde252675239914118664d36a2c24Thomas Grafint rtnl_rule_build_add_request(struct rtnl_rule *tmpl, int flags, 4418a3efffa5b3fde252675239914118664d36a2c24Thomas Graf struct nl_msg **result) 44244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 4438a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return build_rule_msg(tmpl, RTM_NEWRULE, NLM_F_CREATE | flags, 4448a3efffa5b3fde252675239914118664d36a2c24Thomas Graf result); 44544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 44644d362409d5469aed47d19e7908d19bd194493aThomas Graf 44744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 44844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Add a new rule 4491155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk Netlink socket. 45044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg tmpl template with requested changes 45144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags additional netlink message flags 45244d362409d5469aed47d19e7908d19bd194493aThomas Graf * 45344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a netlink message by calling rtnl_rule_build_add_request(), 45444d362409d5469aed47d19e7908d19bd194493aThomas Graf * sends the request to the kernel and waits for the next ACK to be 45544d362409d5469aed47d19e7908d19bd194493aThomas Graf * received and thus blocks until the request has been fullfilled. 45644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 45744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on sucess or a negative error if an error occured. 45844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 4591155370f520cb64657e25153255cf7dc1424317fThomas Grafint rtnl_rule_add(struct nl_sock *sk, struct rtnl_rule *tmpl, int flags) 46044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 46144d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_msg *msg; 4628a3efffa5b3fde252675239914118664d36a2c24Thomas Graf int err; 46344d362409d5469aed47d19e7908d19bd194493aThomas Graf 4648a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if ((err = rtnl_rule_build_add_request(tmpl, flags, &msg)) < 0) 4658a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return err; 46644d362409d5469aed47d19e7908d19bd194493aThomas Graf 4671155370f520cb64657e25153255cf7dc1424317fThomas Graf err = nl_send_auto_complete(sk, msg); 4688a3efffa5b3fde252675239914118664d36a2c24Thomas Graf nlmsg_free(msg); 46944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 47044d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 47144d362409d5469aed47d19e7908d19bd194493aThomas Graf 472cfcfca070355b246028df60da79813f09ed65755Thomas Graf return wait_for_ack(sk); 47344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 47444d362409d5469aed47d19e7908d19bd194493aThomas Graf 47544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 47644d362409d5469aed47d19e7908d19bd194493aThomas Graf 47744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 47844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Rule Deletion 47944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 48044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 48144d362409d5469aed47d19e7908d19bd194493aThomas Graf 48244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 48344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Build a netlink request message to delete a rule 48444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg rule rule to delete 48544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags additional netlink message flags 486054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg result Result pointer 48744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 48844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a new netlink message requesting a deletion of a rule. 48944d362409d5469aed47d19e7908d19bd194493aThomas Graf * The netlink message header isn't fully equipped with all relevant 49044d362409d5469aed47d19e7908d19bd194493aThomas Graf * fields and must thus be sent out via nl_send_auto_complete() 49144d362409d5469aed47d19e7908d19bd194493aThomas Graf * or supplemented as needed. \a rule must point to an existing 49244d362409d5469aed47d19e7908d19bd194493aThomas Graf * address. 49344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 494054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return 0 on success or a negative error code. 49544d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 4968a3efffa5b3fde252675239914118664d36a2c24Thomas Grafint rtnl_rule_build_delete_request(struct rtnl_rule *rule, int flags, 4978a3efffa5b3fde252675239914118664d36a2c24Thomas Graf struct nl_msg **result) 49844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 4998a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return build_rule_msg(rule, RTM_DELRULE, flags, result); 50044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 50144d362409d5469aed47d19e7908d19bd194493aThomas Graf 50244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 50344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Delete a rule 5041155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk Netlink socket. 50544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg rule rule to delete 50644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags additional netlink message flags 50744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 50844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a netlink message by calling rtnl_rule_build_delete_request(), 50944d362409d5469aed47d19e7908d19bd194493aThomas Graf * sends the request to the kernel and waits for the next ACK to be 51044d362409d5469aed47d19e7908d19bd194493aThomas Graf * received and thus blocks until the request has been fullfilled. 51144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 51244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on sucess or a negative error if an error occured. 51344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 5141155370f520cb64657e25153255cf7dc1424317fThomas Grafint rtnl_rule_delete(struct nl_sock *sk, struct rtnl_rule *rule, int flags) 51544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 51644d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_msg *msg; 5178a3efffa5b3fde252675239914118664d36a2c24Thomas Graf int err; 51844d362409d5469aed47d19e7908d19bd194493aThomas Graf 5198a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if ((err = rtnl_rule_build_delete_request(rule, flags, &msg)) < 0) 5208a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return err; 52144d362409d5469aed47d19e7908d19bd194493aThomas Graf 5221155370f520cb64657e25153255cf7dc1424317fThomas Graf err = nl_send_auto_complete(sk, msg); 5238a3efffa5b3fde252675239914118664d36a2c24Thomas Graf nlmsg_free(msg); 52444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 52544d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 52644d362409d5469aed47d19e7908d19bd194493aThomas Graf 527cfcfca070355b246028df60da79813f09ed65755Thomas Graf return wait_for_ack(sk); 52844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 52944d362409d5469aed47d19e7908d19bd194493aThomas Graf 53044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 53144d362409d5469aed47d19e7908d19bd194493aThomas Graf 53244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 53344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Attribute Modification 53444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 53544d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 53644d362409d5469aed47d19e7908d19bd194493aThomas Graf 53744d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_rule_set_family(struct rtnl_rule *rule, int family) 53844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 53944d362409d5469aed47d19e7908d19bd194493aThomas Graf rule->r_family = family; 54044d362409d5469aed47d19e7908d19bd194493aThomas Graf rule->ce_mask |= RULE_ATTR_FAMILY; 54144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 54244d362409d5469aed47d19e7908d19bd194493aThomas Graf 54344d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_rule_get_family(struct rtnl_rule *rule) 54444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 54544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (rule->ce_mask & RULE_ATTR_FAMILY) 54644d362409d5469aed47d19e7908d19bd194493aThomas Graf return rule->r_family; 54744d362409d5469aed47d19e7908d19bd194493aThomas Graf else 54844d362409d5469aed47d19e7908d19bd194493aThomas Graf return AF_UNSPEC; 54944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 55044d362409d5469aed47d19e7908d19bd194493aThomas Graf 551054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartvoid rtnl_rule_set_prio(struct rtnl_rule *rule, uint32_t prio) 55244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 55344d362409d5469aed47d19e7908d19bd194493aThomas Graf rule->r_prio = prio; 55444d362409d5469aed47d19e7908d19bd194493aThomas Graf rule->ce_mask |= RULE_ATTR_PRIO; 55544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 55644d362409d5469aed47d19e7908d19bd194493aThomas Graf 557054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartuint32_t rtnl_rule_get_prio(struct rtnl_rule *rule) 55844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 559054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return rule->r_prio; 56044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 56144d362409d5469aed47d19e7908d19bd194493aThomas Graf 562054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartvoid rtnl_rule_set_mark(struct rtnl_rule *rule, uint32_t mark) 56344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 56444d362409d5469aed47d19e7908d19bd194493aThomas Graf rule->r_mark = mark; 56544d362409d5469aed47d19e7908d19bd194493aThomas Graf rule->ce_mask |= RULE_ATTR_MARK; 56644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 56744d362409d5469aed47d19e7908d19bd194493aThomas Graf 568054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartuint32_t rtnl_rule_get_mark(struct rtnl_rule *rule) 56944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 570054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return rule->r_mark; 57144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 57244d362409d5469aed47d19e7908d19bd194493aThomas Graf 573054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartvoid rtnl_rule_set_mask(struct rtnl_rule *rule, uint32_t mask) 57444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 575054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->r_mask = mask; 576054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->ce_mask |= RULE_ATTR_MASK; 57744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 57844d362409d5469aed47d19e7908d19bd194493aThomas Graf 579054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartuint32_t rtnl_rule_get_mask(struct rtnl_rule *rule) 58044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 581054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return rule->r_mask; 58244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 58344d362409d5469aed47d19e7908d19bd194493aThomas Graf 584054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartvoid rtnl_rule_set_table(struct rtnl_rule *rule, uint32_t table) 58544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 586054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->r_table = table; 587054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->ce_mask |= RULE_ATTR_TABLE; 58844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 58944d362409d5469aed47d19e7908d19bd194493aThomas Graf 590054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartuint32_t rtnl_rule_get_table(struct rtnl_rule *rule) 59144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 592054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return rule->r_table; 59344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 59444d362409d5469aed47d19e7908d19bd194493aThomas Graf 595054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartvoid rtnl_rule_set_dsfield(struct rtnl_rule *rule, uint8_t dsfield) 59644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 597054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->r_dsfield = dsfield; 598054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->ce_mask |= RULE_ATTR_DSFIELD; 59944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 60044d362409d5469aed47d19e7908d19bd194493aThomas Graf 601054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartuint8_t rtnl_rule_get_dsfield(struct rtnl_rule *rule) 60244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 603054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return rule->r_dsfield; 60444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 60544d362409d5469aed47d19e7908d19bd194493aThomas Graf 60644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline int __assign_addr(struct rtnl_rule *rule, struct nl_addr **pos, 607054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart struct nl_addr *new, int flag) 60844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 60944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (rule->ce_mask & RULE_ATTR_FAMILY) { 61044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (new->a_family != rule->r_family) 6118a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_AF_MISMATCH; 61244d362409d5469aed47d19e7908d19bd194493aThomas Graf } else 61344d362409d5469aed47d19e7908d19bd194493aThomas Graf rule->r_family = new->a_family; 61444d362409d5469aed47d19e7908d19bd194493aThomas Graf 61544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (*pos) 61644d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_put(*pos); 61744d362409d5469aed47d19e7908d19bd194493aThomas Graf 61844d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_get(new); 61944d362409d5469aed47d19e7908d19bd194493aThomas Graf *pos = new; 62044d362409d5469aed47d19e7908d19bd194493aThomas Graf 62144d362409d5469aed47d19e7908d19bd194493aThomas Graf rule->ce_mask |= (flag | RULE_ATTR_FAMILY); 62244d362409d5469aed47d19e7908d19bd194493aThomas Graf 62344d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 62444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 62544d362409d5469aed47d19e7908d19bd194493aThomas Graf 62644d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_rule_set_src(struct rtnl_rule *rule, struct nl_addr *src) 62744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 628054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return __assign_addr(rule, &rule->r_src, src, RULE_ATTR_SRC); 62944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 63044d362409d5469aed47d19e7908d19bd194493aThomas Graf 63144d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_addr *rtnl_rule_get_src(struct rtnl_rule *rule) 63244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 633054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return rule->r_src; 63444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 63544d362409d5469aed47d19e7908d19bd194493aThomas Graf 63644d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_rule_set_dst(struct rtnl_rule *rule, struct nl_addr *dst) 63744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 638054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return __assign_addr(rule, &rule->r_dst, dst, RULE_ATTR_DST); 63944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 64044d362409d5469aed47d19e7908d19bd194493aThomas Graf 64144d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_addr *rtnl_rule_get_dst(struct rtnl_rule *rule) 64244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 643054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return rule->r_dst; 64444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 64544d362409d5469aed47d19e7908d19bd194493aThomas Graf 64644d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_rule_set_iif(struct rtnl_rule *rule, const char *dev) 64744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 64844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (strlen(dev) > IFNAMSIZ-1) 6498a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_RANGE; 65044d362409d5469aed47d19e7908d19bd194493aThomas Graf 651054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart strcpy(rule->r_iifname, dev); 652054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->ce_mask |= RULE_ATTR_IIFNAME; 65344d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 65444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 65544d362409d5469aed47d19e7908d19bd194493aThomas Graf 65644d362409d5469aed47d19e7908d19bd194493aThomas Grafchar *rtnl_rule_get_iif(struct rtnl_rule *rule) 65744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 658054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (rule->ce_mask & RULE_ATTR_IIFNAME) 659054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return rule->r_iifname; 66044d362409d5469aed47d19e7908d19bd194493aThomas Graf else 66144d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 66244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 66344d362409d5469aed47d19e7908d19bd194493aThomas Graf 664054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartint rtnl_rule_set_oif(struct rtnl_rule *rule, const char *dev) 66544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 666054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (strlen(dev) > IFNAMSIZ-1) 667054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return -NLE_RANGE; 668054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 669054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart strcpy(rule->r_oifname, dev); 670054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->ce_mask |= RULE_ATTR_OIFNAME; 671054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return 0; 67244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 67344d362409d5469aed47d19e7908d19bd194493aThomas Graf 674054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartchar *rtnl_rule_get_oif(struct rtnl_rule *rule) 67544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 676054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart if (rule->ce_mask & RULE_ATTR_OIFNAME) 677054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return rule->r_oifname; 67844d362409d5469aed47d19e7908d19bd194493aThomas Graf else 679054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return NULL; 680054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart} 681054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 682054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartvoid rtnl_rule_set_action(struct rtnl_rule *rule, uint8_t action) 683054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{ 684054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->r_action = action; 685054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->ce_mask |= RULE_ATTR_ACTION; 686054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart} 687054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 688054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartuint8_t rtnl_rule_get_action(struct rtnl_rule *rule) 689054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{ 690054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return rule->r_action; 69144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 69244d362409d5469aed47d19e7908d19bd194493aThomas Graf 693535e83162249ed6274ba46bc72d8cc683ba20e17Thomas Grafvoid rtnl_rule_set_realms(struct rtnl_rule *rule, uint32_t realms) 69444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 695054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->r_flow = realms; 696054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->ce_mask |= RULE_ATTR_FLOW; 69744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 69844d362409d5469aed47d19e7908d19bd194493aThomas Graf 699535e83162249ed6274ba46bc72d8cc683ba20e17Thomas Grafuint32_t rtnl_rule_get_realms(struct rtnl_rule *rule) 70044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 701054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return rule->r_flow; 702054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart} 703054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 704054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartvoid rtnl_rule_set_goto(struct rtnl_rule *rule, uint32_t ref) 705054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{ 706054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->r_goto = ref; 707054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart rule->ce_mask |= RULE_ATTR_GOTO; 708054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart} 709054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart 710054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartuint32_t rtnl_rule_get_goto(struct rtnl_rule *rule) 711054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{ 712054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart return rule->r_goto; 71344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 71444d362409d5469aed47d19e7908d19bd194493aThomas Graf 71544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 71644d362409d5469aed47d19e7908d19bd194493aThomas Graf 71744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_object_ops rule_obj_ops = { 71844d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_name = "route/rule", 71944d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_size = sizeof(struct rtnl_rule), 72044d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_free_data = rule_free_data, 72144d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_clone = rule_clone, 722d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf .oo_dump = { 723d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_LINE] = rule_dump_line, 724d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_DETAILS] = rule_dump_details, 725d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_STATS] = rule_dump_stats, 726d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf }, 72744d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_compare = rule_compare, 72844d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_attrs2str = rule_attrs2str, 72944d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_id_attrs = ~0, 73044d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 73144d362409d5469aed47d19e7908d19bd194493aThomas Graf 73244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_cache_ops rtnl_rule_ops = { 73344d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_name = "route/rule", 734054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart .co_hdrsize = sizeof(struct fib_rule_hdr), 73544d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_msgtypes = { 73644d362409d5469aed47d19e7908d19bd194493aThomas Graf { RTM_NEWRULE, NL_ACT_NEW, "new" }, 73744d362409d5469aed47d19e7908d19bd194493aThomas Graf { RTM_DELRULE, NL_ACT_DEL, "del" }, 73844d362409d5469aed47d19e7908d19bd194493aThomas Graf { RTM_GETRULE, NL_ACT_GET, "get" }, 73944d362409d5469aed47d19e7908d19bd194493aThomas Graf END_OF_MSGTYPES_LIST, 74044d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 74144d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_protocol = NETLINK_ROUTE, 74244d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_request_update = rule_request_update, 74344d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_msg_parser = rule_msg_parser, 74444d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_obj_ops = &rule_obj_ops, 74544d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 74644d362409d5469aed47d19e7908d19bd194493aThomas Graf 74744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __init rule_init(void) 74844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 74944d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_cache_mngt_register(&rtnl_rule_ops); 75044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 75144d362409d5469aed47d19e7908d19bd194493aThomas Graf 75244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __exit rule_exit(void) 75344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 75444d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_cache_mngt_unregister(&rtnl_rule_ops); 75544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 75644d362409d5469aed47d19e7908d19bd194493aThomas Graf 75744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 758