#ifndef _IPV6_UTILS_H #define _IPV6_UTILS_H #ifdef __cpluscplus extern "C" { #endif #include #include /* * IPv6 Header Format * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |Version| Traffic Class | Flow Label | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Payload Length | Next Header | Hop Limit | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | * + + * | | * + Source Address + * | | * + + * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | * + + * | | * + Destination Address + * | | * + + * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * Fragment Header * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Next Header | Reserved | Fragment Offset |Res|M| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Identification | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /****************************************************************************** * get ******************************************************************************/ static inline uint8_t ipv6_hdr_get_version(const struct ip6_hdr *hdr) { return (ntohl(hdr->ip6_flow) & 0xf0000000) >> 28; } static inline uint8_t ipv6_hdr_get_traffic_class(const struct ip6_hdr *hdr) { return (ntohl(hdr->ip6_flow) & 0x0ff00000) >> 20; } static inline uint32_t ipv6_hdr_get_flow_label(const struct ip6_hdr *hdr) { return ntohl(hdr->ip6_flow) & 0x000fffff; } static inline uint16_t ipv6_hdr_get_payload_len(const struct ip6_hdr *hdr) { return ntohs(hdr->ip6_plen); } static inline uint8_t ipv6_hdr_get_next_header(const struct ip6_hdr *hdr) { return hdr->ip6_nxt; } static inline uint8_t ipv6_hdr_get_hop_limit(const struct ip6_hdr *hdr) { return hdr->ip6_hlim; } static inline struct in6_addr ipv6_hdr_get_src_in6_addr(const struct ip6_hdr *hdr) { return hdr->ip6_src; } static inline struct in6_addr ipv6_hdr_get_dst_in6_addr(const struct ip6_hdr *hdr) { return hdr->ip6_dst; } static inline struct ip6_frag *ipv6_hdr_get_frag_ext(const struct ip6_hdr *hdr) { if (hdr->ip6_nxt != IPPROTO_FRAGMENT) { return NULL; } return (struct ip6_frag *)((char *)hdr + sizeof(struct ip6_hdr)); } /****************************************************************************** * set ******************************************************************************/ static inline void ipv6_hdr_set_version(struct ip6_hdr *hdr, uint8_t version) { hdr->ip6_flow = htonl((ntohl(hdr->ip6_flow) & 0x0fffffff) | (version << 28)); } static inline void ipv6_hdr_set_traffic_class(struct ip6_hdr *hdr, uint8_t traffic_class) { hdr->ip6_flow = htonl((ntohl(hdr->ip6_flow) & 0xf00fffff) | (traffic_class << 20)); } static inline void ipv6_hdr_set_flow_label(struct ip6_hdr *hdr, uint32_t flow_label) { hdr->ip6_flow = htonl((ntohl(hdr->ip6_flow) & 0xfff00000) | flow_label); } static inline void ipv6_hdr_set_payload_len(struct ip6_hdr *hdr, uint16_t payload_len) { hdr->ip6_plen = htons(payload_len); } static inline void ipv6_hdr_set_next_header(struct ip6_hdr *hdr, uint8_t next_header) { hdr->ip6_nxt = next_header; } static inline void ipv6_hdr_set_hop_limit(struct ip6_hdr *hdr, uint8_t hop_limit) { hdr->ip6_hlim = hop_limit; } static inline void ipv6_hdr_set_src_in6_addr(struct ip6_hdr *hdr, struct in6_addr src_addr) { hdr->ip6_src = src_addr; } static inline void ipv6_hdr_set_dst_in6_addr(struct ip6_hdr *hdr, struct in6_addr dst_addr) { hdr->ip6_dst = dst_addr; } /****************************************************************************** * IPv6 frag extension headers ******************************************************************************/ static inline uint8_t ipv6_frag_get_next_header(const struct ip6_frag *frag) { return frag->ip6f_nxt; } static inline uint16_t ipv6_frag_get_offset(const struct ip6_frag *frag) { return ntohs(frag->ip6f_offlg & IP6F_OFF_MASK); } static inline uint32_t ipv6_frag_get_ident(const struct ip6_frag *frag) { return ntohl(frag->ip6f_ident); } static inline bool ipv6_frag_get_more(const struct ip6_frag *frag) { return (frag->ip6f_offlg & IP6F_MORE_FRAG); } static inline void ipv6_frag_set_next_header(struct ip6_frag *frag, uint8_t next_header) { frag->ip6f_nxt = next_header; } static inline void ipv6_frag_set_offset(struct ip6_frag *frag, uint16_t offset) { frag->ip6f_offlg = (frag->ip6f_offlg & ~IP6F_OFF_MASK) | htons(offset); } static inline void ipv6_frag_set_ident(struct ip6_frag *frag, uint32_t ident) { frag->ip6f_ident = htonl(ident); } static inline void ipv6_frag_set_more(struct ip6_frag *frag, bool more) { if (more) { frag->ip6f_offlg |= IP6F_MORE_FRAG; } else { frag->ip6f_offlg &= ~IP6F_MORE_FRAG; } } #ifdef __cpluscplus } #endif #endif