int rtnl_u32_add_key_uint8(struct rtnl_cls *cls, uint8_t val, uint8_t mask, int off, int offmask) { int shift = 24 - 8 * (off & 3); return rtnl_u32_add_key(cls, htonl((uint32_t)val << shift), htonl((uint32_t)mask << shift), off & ~3, offmask); }
/** * Append new selector key to match a 16-bit number * * @arg cls classifier to be modified * @arg val value to be matched (host byte-order) * @arg mask mask to be applied before matching (host byte-order) * @arg off offset, in bytes, to start matching * @arg offmask offset mask */ int rtnl_u32_add_key_uint16(struct rtnl_cls *cls, uint16_t val, uint16_t mask, int off, int offmask) { int shift = ((off & 3) == 0 ? 16 : 0); if (off % 2) return -NLE_INVAL; return rtnl_u32_add_key(cls, htonl((uint32_t)val << shift), htonl((uint32_t)mask << shift), off & ~3, offmask); }
int rtnl_u32_add_key_in6_addr(struct rtnl_cls *cls, const struct in6_addr *addr, uint8_t bitmask, int off, int offmask) { int i, err; for (i = 1; i <= 4; i++) { if (32 * i - bitmask <= 0) { if ((err = rtnl_u32_add_key(cls, addr->s6_addr32[i-1], 0xFFFFFFFF, off+4*(i-1), offmask)) < 0) return err; } else if (32 * i - bitmask < 32) { uint32_t mask = 0xFFFFFFFF << (32 * i - bitmask); if ((err = rtnl_u32_add_key(cls, addr->s6_addr32[i-1], htonl(mask), off+4*(i-1), offmask)) < 0) return err; } /* otherwise, if (32*i - bitmask >= 32) no key is generated */ } return 0; }
int rtnl_u32_add_key_in_addr(struct rtnl_cls *cls, const struct in_addr *addr, uint8_t bitmask, int off, int offmask) { uint32_t mask = 0xFFFFFFFF << (32 - bitmask); return rtnl_u32_add_key(cls, addr->s_addr, htonl(mask), off, offmask); }
/** * Append new selector key to match a 32-bit number * * @arg cls classifier to be modified * @arg val value to be matched (host byte-order) * @arg mask mask to be applied before matching (host byte-order) * @arg off offset, in bytes, to start matching * @arg offmask offset mask */ int rtnl_u32_add_key_uint32(struct rtnl_cls *cls, uint32_t val, uint32_t mask, int off, int offmask) { return rtnl_u32_add_key(cls, htonl(val), htonl(mask), off & ~3, offmask); }
Try<Nothing> encode<icmp::Classifier>( const Netlink<struct rtnl_cls>& cls, const icmp::Classifier& classifier) { // ICMP packets are one type of IP packets. rtnl_cls_set_protocol(cls.get(), ETH_P_IP); int error = rtnl_tc_set_kind(TC_CAST(cls.get()), "u32"); if (error != 0) { return Error( "Failed to set the kind of the classifier: " + string(nl_geterror(error))); } // To avoid confusion, we only use u32 selectors which are used to // match arbitrary 32-bit content in a packet. // Format of an IP packet at offset 8. The IP protocol field is at // offset 9. ICMP has protocol = 1. // +--------+--------+--------+--------+ // | X | Proto. | X | X | // +--------+--------+--------+--------+ // Offset: 8 9 10 11 uint32_t protocol = 0x00010000; uint32_t mask = 0x00ff0000; // Ignore offset 8, 10, 11. // To match ICMP packets (protocol = 1). error = rtnl_u32_add_key( cls.get(), htonl(protocol), htonl(mask), 8, // Offset from which to start matching. 0); if (error != 0) { return Error( "Failed to add selector for IP protocol: " + string(nl_geterror(error))); } if (classifier.destinationIP.isSome()) { Try<struct in_addr> in = classifier.destinationIP.get().in(); if (in.isError()) { return Error("Destination IP is not an IPv4 address"); } // To match those IP packets that have the given destination IP. error = rtnl_u32_add_key( cls.get(), in.get().s_addr, htonl(0xffffffff), 16, // Offset from which to start matching. 0); if (error != 0) { return Error( "Failed to add selector for destination IP address: " + string(nl_geterror(error))); } } return Nothing(); }