ea[0] &= ~1; /* Unicast. */
ea[0] |= 2; /* Private. */
}
+/* Returns true if 'ea' is a reserved multicast address, that a bridge must
+ * never forward, false otherwise. */
+static inline bool eth_addr_is_reserved(const uint8_t ea[ETH_ADDR_LEN])
+{
+ return (ea[0] == 0x01
+ && ea[1] == 0x80
+ && ea[2] == 0xc2
+ && ea[3] == 0x00
+ && ea[4] == 0x00
+ && (ea[5] & 0xf0) == 0x00);
+}
#define ETH_ADDR_FMT \
"%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8
} __attribute__((packed));
BUILD_ASSERT_DECL(VLAN_ETH_HEADER_LEN == sizeof(struct vlan_eth_header));
+/* The "(void) (ip)[0]" below has no effect on the value, since it's the first
+ * argument of a comma expression, but it makes sure that 'ip' is a pointer.
+ * This is useful since a common mistake is to pass an integer instead of a
+ * pointer to IP_ARGS. */
#define IP_FMT "%"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8
#define IP_ARGS(ip) \
- ((uint8_t *) ip)[0], \
+ ((void) (ip)[0], ((uint8_t *) ip)[0]), \
((uint8_t *) ip)[1], \
((uint8_t *) ip)[2], \
((uint8_t *) ip)[3]
};
BUILD_ASSERT_DECL(IP_HEADER_LEN == sizeof(struct ip_header));
+#define ICMP_HEADER_LEN 4
+struct icmp_header {
+ uint8_t icmp_type;
+ uint8_t icmp_code;
+ uint16_t icmp_csum;
+};
+BUILD_ASSERT_DECL(ICMP_HEADER_LEN == sizeof(struct icmp_header));
+
#define UDP_HEADER_LEN 8
struct udp_header {
uint16_t udp_src;