Index: sys/netinet/ip_options.c =================================================================== --- sys/netinet/ip_options.c +++ sys/netinet/ip_options.c @@ -101,7 +101,7 @@ int ip_dooptions(struct mbuf *m, int pass) { - struct ip *ip = mtod(m, struct ip *); + struct ip *ip = mtod(m); u_char *cp; struct in_ifaddr *ia; int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; @@ -453,7 +453,7 @@ * First, save first hop for return route. */ p = &(opts->ip_srcrt.route[opts->ip_nhops - 1]); - *(mtod(m, struct in_addr *)) = *p--; + *((struct in_addr *)mtod(m)) = *p--; /* * Copy option fields and padding (nop) to mbuf. @@ -486,7 +486,7 @@ void ip_stripoptions(struct mbuf *m) { - struct ip *ip = mtod(m, struct ip *); + struct ip *ip = mtod(m); int olen; olen = (ip->ip_hl << 2) - sizeof(struct ip); @@ -510,9 +510,9 @@ struct mbuf * ip_insertoptions(struct mbuf *m, struct mbuf *opt, int *phlen) { - struct ipoption *p = mtod(opt, struct ipoption *); + struct ipoption *p = mtod(opt); struct mbuf *n; - struct ip *ip = mtod(m, struct ip *); + struct ip *ip = mtod(m); unsigned optlen; optlen = opt->m_len - sizeof(p->ipopt_dst); @@ -537,14 +537,14 @@ m = n; m->m_len = optlen + sizeof(struct ip); m->m_data += max_linkhdr; - bcopy(ip, mtod(m, void *), sizeof(struct ip)); + bcopy(ip, mtod(m), sizeof(struct ip)); } else { m->m_data -= optlen; m->m_len += optlen; m->m_pkthdr.len += optlen; - bcopy(ip, mtod(m, void *), sizeof(struct ip)); + bcopy(ip, mtod(m), sizeof(struct ip)); } - ip = mtod(m, struct ip *); + ip = (struct ip *)mtod(m); bcopy(p->ipopt_list, ip + 1, optlen); *phlen = sizeof(struct ip) + optlen; ip->ip_v = IPVERSION; @@ -636,9 +636,9 @@ goto bad; cnt = m->m_len; m->m_len += sizeof(struct in_addr); - cp = mtod(m, u_char *) + sizeof(struct in_addr); - bcopy(mtod(m, void *), cp, (unsigned)cnt); - bzero(mtod(m, void *), sizeof(struct in_addr)); + cp = (u_char *)mtod(m) + sizeof(struct in_addr); + bcopy(mtod(m), cp, (unsigned)cnt); + bzero(mtod(m), sizeof(struct in_addr)); for (; cnt > 0; cnt -= optlen, cp += optlen) { opt = cp[IPOPT_OPTVAL]; @@ -722,7 +722,7 @@ int ip_checkrouteralert(struct mbuf *m) { - struct ip *ip = mtod(m, struct ip *); + struct ip *ip = mtod(m); u_char *cp; int opt, optlen, cnt, found_ra; Index: sys/sys/mbuf.h =================================================================== --- sys/sys/mbuf.h +++ sys/sys/mbuf.h @@ -103,13 +103,45 @@ #ifdef _KERNEL /*- - * Macro for type conversion: convert mbuf pointer to data pointer of correct - * type: + * Convert mbuf pointers into various possible pointers to mbuf data. * - * mtod(m, t) -- Convert mbuf pointer to data pointer of correct type. - * mtodo(m, o) -- Same as above but with offset 'o' into data. + * mtod(m) -- Convert mbuf pointer to void pointer of correct const. + * mtod(m, t) -- Convert mbuf pointer to pointer of type t (legacy) + * mtodo(m, o) -- Convert mbuf pointer to void pointer at offset 'o'. */ -#define mtod(m, t) ((t)((m)->m_data)) +#if __STDC_VERSION__ >= 201112L +#define __mtod_1(m) \ + _Generic((m), \ + const struct mbuf *: (const void *)(m)->m_data, \ + struct mbuf *: (void *)(m)->m_data \ + ) +#else /* < C11 */ +#define __mtod_1(m) __DECONST(void *, (m)->m_data) +#endif + +#define __mtod_2(m, t) ((t)((m)->m_data)) + +/* + * Ugliness starting here encapsulates an mtod() macro that takes either one or + * two parameters. + * + * This first bit counts the number of variadic arguments in '...'. That is, + * __mtod_narg() returns either 1 or 2. + */ +#define __mtod_arg_n(_1, _2, N, ...) N +#define __mtod_narg_(...) __mtod_arg_n(__VA_ARGS__) +#define __mtod_narg(...) __mtod_narg_(__VA_ARGS__, 2, 1) + +/* + * Given the number of arguments counted by __mtod_narg(), __mtod() + * concatenates the number to a prefix to select the correct version of the + * macro. + */ +#define __mtod(N, ...) __CONCAT(__mtod_, N)(__VA_ARGS__) + +#define mtod(...) __mtod(__mtod_narg(__VA_ARGS__), __VA_ARGS__) +/* End of mtod(m [, t]) ugliness. */ + #define mtodo(m, o) ((void *)(((m)->m_data) + (o))) /* Index: tools/coccinelle/convert_mtod_2_to_1_arg.cocci =================================================================== --- /dev/null +++ tools/coccinelle/convert_mtod_2_to_1_arg.cocci @@ -0,0 +1,36 @@ +// Convert mtod() macro to a typeless version, leaving explicit casts +// for now in case people rely on them for legibility in large +// functions. + +// Drop explicit casts to void* and const void*, as those cannot possibly +// inform about the resulting data type. + +// Also drop casts when mtod() is used during declaration (bad style, but it +// exists in the codebase). + +@r1@ +expression m; +type t; +identifier i; +@@ + +-t i = mtod(m, t); ++t i = mtod(m); + + +@r2@ +expression m; +type t; +identifier i; +@@ + +( +-mtod(m, void *) ++mtod(m) +| +-mtod(m, const void *) ++mtod(m) +| +-mtod(m, t) ++(t)mtod(m) +)