#ifndef _IPV4_UTILS_H #define _IPV4_UTILS_H #ifdef __cplusplus extern "C" { #endif #include #include #include /* * Internet 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| IHL |Type of Service| Total Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Identification |Flags| Fragment Offset | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Time to Live | Protocol | Header Checksum | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Source Address | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Destination Address | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Options | Padding | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /****************************************************************************** * get ******************************************************************************/ static inline uint8_t ipv4_hdr_get_version(const struct ip *hdr) { return hdr->ip_v; } static inline uint8_t ipv4_hdr_get_hdr_len(const struct ip *hdr) { return hdr->ip_hl << 2; } static inline uint8_t ipv4_hdr_get_tos(const struct ip *hdr) { return hdr->ip_tos; } static inline uint16_t ipv4_hdr_get_total_len(const struct ip *hdr) { return ntohs(hdr->ip_len); } static inline uint16_t ipv4_hdr_get_ipid(const struct ip *hdr) { return ntohs(hdr->ip_id); } static inline uint8_t ipv4_hdr_get_flags(const struct ip *hdr) { return (ntohs(hdr->ip_off) & (~IP_OFFMASK)) >> 13; } static inline bool ipv4_hdr_get_rf_flag(const struct ip *hdr) { return (ntohs(hdr->ip_off) & IP_RF) != 0; } static inline bool ipv4_hdr_get_df_flag(const struct ip *hdr) { return (ntohs(hdr->ip_off) & IP_DF) != 0; } static inline bool ipv4_hdr_get_mf_flag(const struct ip *hdr) { return (ntohs(hdr->ip_off) & IP_MF) != 0; } static inline uint16_t ipv4_hdr_get_frag_offset(const struct ip *hdr) { return (ntohs(hdr->ip_off) & IP_OFFMASK) << 3; } static inline uint8_t ipv4_hdr_get_ttl(const struct ip *hdr) { return hdr->ip_ttl; } static inline uint8_t ipv4_hdr_get_proto(const struct ip *hdr) { return hdr->ip_p; } static inline uint16_t ipv4_hdr_get_checksum(const struct ip *hdr) { return ntohs(hdr->ip_sum); } static inline uint32_t ipv4_hdr_get_src_addr(const struct ip *hdr) { return ntohl(hdr->ip_src.s_addr); } static inline uint32_t ipv4_hdr_get_dst_addr(const struct ip *hdr) { return ntohl(hdr->ip_dst.s_addr); } static inline struct in_addr ipv4_hdr_get_src_in_addr(const struct ip *hdr) { return hdr->ip_src; } static inline struct in_addr ipv4_hdr_get_dst_in_addr(const struct ip *hdr) { return hdr->ip_dst; } static inline uint8_t ipv4_hdr_get_opt_len(const struct ip *hdr) { return ipv4_hdr_get_hdr_len(hdr) - sizeof(struct ip); } static inline const char *ipv4_hdr_get_opt_data(const struct ip *hdr) { if (ipv4_hdr_get_opt_len(hdr) == 0) { return NULL; } return (const char *)hdr + sizeof(struct ip); } /****************************************************************************** * set ******************************************************************************/ static inline void ipv4_hdr_set_version(struct ip *hdr, uint8_t version) { hdr->ip_v = version; } static inline void ipv4_hdr_set_hdr_len(struct ip *hdr, uint8_t hdr_len) { hdr->ip_hl = hdr_len >> 2; } static inline void ipv4_hdr_set_tos(struct ip *hdr, uint8_t tos) { hdr->ip_tos = tos; } static inline void ipv4_hdr_set_total_len(struct ip *hdr, uint16_t total_len) { hdr->ip_len = htons(total_len); } static inline void ipv4_hdr_set_ipid(struct ip *hdr, uint16_t ipid) { hdr->ip_id = htons(ipid); } static inline void ipv4_hdr_set_flags(struct ip *hdr, uint8_t flags) { hdr->ip_off = htons((flags << 13) | (ntohs(hdr->ip_off) & IP_OFFMASK)); } static inline void ipv4_hdr_set_rf_flag(struct ip *hdr, bool flag) { if (flag) { hdr->ip_off = htons(ntohs(hdr->ip_off) | IP_RF); } else { hdr->ip_off = htons(ntohs(hdr->ip_off) & ~IP_RF); } } static inline void ipv4_hdr_set_df_flag(struct ip *hdr, bool flag) { if (flag) { hdr->ip_off = htons(ntohs(hdr->ip_off) | IP_DF); } else { hdr->ip_off = htons(ntohs(hdr->ip_off) & ~IP_DF); } } static inline void ipv4_hdr_set_mf_flag(struct ip *hdr, bool flag) { if (flag) { hdr->ip_off = htons(ntohs(hdr->ip_off) | IP_MF); } else { hdr->ip_off = htons(ntohs(hdr->ip_off) & ~IP_MF); } } static inline void ipv4_hdr_set_frag_offset(struct ip *hdr, uint16_t frag_offset) { hdr->ip_off = htons((frag_offset >> 3) | (ntohs(hdr->ip_off) & ~IP_OFFMASK)); } static inline void ipv4_hdr_set_ttl(struct ip *hdr, uint8_t ttl) { hdr->ip_ttl = ttl; } static inline void ipv4_hdr_set_protocol(struct ip *hdr, uint8_t protocol) { hdr->ip_p = protocol; } static inline void ipv4_hdr_set_checksum(struct ip *hdr, uint16_t checksum) { hdr->ip_sum = htons(checksum); } static inline void ipv4_hdr_set_src_addr(struct ip *hdr, uint32_t saddr) { hdr->ip_src.s_addr = htonl(saddr); } static inline void ipv4_hdr_set_dst_addr(struct ip *hdr, uint32_t daddr) { hdr->ip_dst.s_addr = htonl(daddr); } static inline void ipv4_hdr_set_src_in_addr(struct ip *hdr, struct in_addr saddr) { hdr->ip_src = saddr; } static inline void ipv4_hdr_set_dst_in_addr(struct ip *hdr, struct in_addr daddr) { hdr->ip_dst = daddr; } static inline void ipv4_hdr_set_opt_len(struct ip *hdr, uint8_t opt_len) { ipv4_hdr_set_hdr_len(hdr, opt_len + sizeof(struct ip)); } // must be called after ipv4_hdr_set_opt_len static inline void ipv4_hdr_set_opt_data(struct ip *hdr, const char *opt_data) { memcpy((char *)hdr + sizeof(struct ip), opt_data, ipv4_hdr_get_opt_len(hdr)); } #ifdef __cplusplus } #endif #endif