36#include <sys/kernel.h>
37#include <sys/endian.h>
38#include <sys/malloc.h>
40#include <sys/socket.h>
43#include <net/ethernet.h>
45#include <net/if_vlan_var.h>
47#include <netinet/in.h>
48#include <netinet/ip.h>
49#include <netinet/ip6.h>
50#include <netinet/tcp.h>
51#include <netinet/udp.h>
52#include <machine/in_cksum.h>
78#define ERROUT(x) { error = (x); goto done; }
166 priv = malloc(
sizeof(*
priv), M_NETGRAPH, M_WAITOK|M_ZERO);
211 *((uint8_t *) resp->
data) =
priv->dlt;
219 switch (*(uint8_t *) msg->
data)
233 if (
priv->conf == NULL)
259 free(
priv->conf, M_NETGRAPH);
261 priv->conf = newconf;
293#define PULLUP_CHECK(mbuf, length) do { \
294 pullup_len += length; \
295 if (((mbuf)->m_pkthdr.len < pullup_len) || \
296 (pullup_len > MHLEN)) { \
299 if ((mbuf)->m_len < pullup_len && \
300 (((mbuf) = m_pullup((mbuf), pullup_len)) == NULL)) { \
307checksum_ipv4(
priv_p priv,
struct mbuf *m,
int l3_offset)
314 pullup_len = l3_offset;
317 ip4 = (
struct ip *) mtodo(m, l3_offset);
319 if (ip4->ip_v != IPVERSION)
322 hlen = ip4->ip_hl << 2;
323 plen = ntohs(ip4->ip_len);
325 if (hlen <
sizeof(
struct ip) || m->m_pkthdr.len < l3_offset + plen)
328 if (m->m_pkthdr.csum_flags & CSUM_IP) {
331 if ((
priv->conf->csum_offload & CSUM_IP) == 0) {
332 if (hlen ==
sizeof(
struct ip))
333 ip4->ip_sum = in_cksum_hdr(ip4);
335 ip4->ip_sum = in_cksum_skip(m, l3_offset + hlen, l3_offset);
337 m->m_pkthdr.csum_flags &= ~CSUM_IP;
343 pullup_len = l3_offset + hlen;
346 if (ip4->ip_off & htons(IP_MF|IP_OFFMASK)) {
347 m->m_pkthdr.csum_flags &= ~(CSUM_TCP|CSUM_UDP);
354 if (m->m_pkthdr.csum_flags & CSUM_TCP) {
358 th = (
struct tcphdr *) mtodo(m, l3_offset + hlen);
360 th->th_sum = in_pseudo(ip4->ip_src.s_addr,
361 ip4->ip_dst.s_addr, htons(ip4->ip_p + plen - hlen));
363 if ((
priv->conf->csum_offload & CSUM_TCP) == 0) {
364 th->th_sum = in_cksum_skip(m, l3_offset + plen, l3_offset + hlen);
365 m->m_pkthdr.csum_flags &= ~CSUM_TCP;
371 m->m_pkthdr.csum_flags &= ~CSUM_UDP;
375 if (m->m_pkthdr.csum_flags & CSUM_UDP) {
379 uh = (
struct udphdr *) mtodo(m, l3_offset + hlen);
381 uh->uh_sum = in_pseudo(ip4->ip_src.s_addr,
382 ip4->ip_dst.s_addr, htons(ip4->ip_p + plen - hlen));
384 if ((
priv->conf->csum_offload & CSUM_UDP) == 0) {
385 uh->uh_sum = in_cksum_skip(m,
386 l3_offset + plen, l3_offset + hlen);
391 m->m_pkthdr.csum_flags &= ~CSUM_UDP;
397 m->m_pkthdr.csum_flags &= ~CSUM_TCP;
401 m->m_pkthdr.csum_flags &= ~(CSUM_TCP|CSUM_UDP);
405 m->m_pkthdr.csum_flags &= ~NG_CHECKSUM_CSUM_IPV6;
416checksum_ipv6(
priv_p priv,
struct mbuf *m,
int l3_offset)
419 struct ip6_ext *ip6e = NULL;
425 pullup_len = l3_offset;
428 ip6 = (
struct ip6_hdr *) mtodo(m, l3_offset);
430 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION)
433 hlen =
sizeof(
struct ip6_hdr);
434 plen = ntohs(ip6->ip6_plen) + hlen;
436 if (m->m_pkthdr.len < l3_offset + plen)
444 case IPPROTO_DSTOPTS:
445 case IPPROTO_HOPOPTS:
446 case IPPROTO_ROUTING:
448 ip6e = (
struct ip6_ext *) mtodo(m, l3_offset + hlen);
449 nxt = ip6e->ip6e_nxt;
450 hlen += (ip6e->ip6e_len + 1) << 3;
451 pullup_len = l3_offset + hlen;
456 ip6e = (
struct ip6_ext *) mtodo(m, l3_offset + hlen);
457 nxt = ip6e->ip6e_nxt;
458 hlen += (ip6e->ip6e_len + 2) << 2;
459 pullup_len = l3_offset + hlen;
462 case IPPROTO_FRAGMENT:
464 m->m_pkthdr.csum_flags &= ~(CSUM_TCP_IPV6|CSUM_UDP_IPV6);
480 if (m->m_pkthdr.csum_flags & CSUM_TCP_IPV6) {
484 th = (
struct tcphdr *) mtodo(m, l3_offset + hlen);
486 th->th_sum = in6_cksum_pseudo(ip6, plen - hlen, nxt, 0);
488 if ((
priv->conf->csum_offload & CSUM_TCP_IPV6) == 0) {
489 th->th_sum = in_cksum_skip(m, l3_offset + plen, l3_offset + hlen);
490 m->m_pkthdr.csum_flags &= ~CSUM_TCP_IPV6;
496 m->m_pkthdr.csum_flags &= ~CSUM_UDP_IPV6;
500 if (m->m_pkthdr.csum_flags & CSUM_UDP_IPV6) {
504 uh = (
struct udphdr *) mtodo(m, l3_offset + hlen);
506 uh->uh_sum = in6_cksum_pseudo(ip6, plen - hlen, nxt, 0);
508 if ((
priv->conf->csum_offload & CSUM_UDP_IPV6) == 0) {
509 uh->uh_sum = in_cksum_skip(m,
510 l3_offset + plen, l3_offset + hlen);
515 m->m_pkthdr.csum_flags &= ~CSUM_UDP_IPV6;
521 m->m_pkthdr.csum_flags &= ~CSUM_TCP_IPV6;
525 m->m_pkthdr.csum_flags &= ~(CSUM_TCP_IPV6|CSUM_UDP_IPV6);
529 m->m_pkthdr.csum_flags &= ~NG_CHECKSUM_CSUM_IPV4;
552#define PULLUP_CHECK(mbuf, length) do { \
553 pullup_len += length; \
554 if (((mbuf)->m_pkthdr.len < pullup_len) || \
555 (pullup_len > MHLEN)) { \
559 if ((mbuf)->m_len < pullup_len && \
560 (((mbuf) = m_pullup((mbuf), pullup_len)) == NULL)) { \
566 if (!(
priv->conf && hook ==
priv->in && m && (m->m_flags & M_PKTHDR)))
569 m->m_pkthdr.csum_flags |=
priv->conf->csum_flags;
573 struct ether_header *eh;
578 m = m_unshare(m, M_NOWAIT);
587 eh = mtod(m,
struct ether_header *);
588 etype = ntohs(eh->ether_type);
608 if (
etype == ETHERTYPE_IP &&
610 error = checksum_ipv4(
priv, m, pullup_len);
611 if (error == ENOBUFS)
616 if (
etype == ETHERTYPE_IPV6 &&
618 error = checksum_ipv6(
priv, m, pullup_len);
619 if (error == ENOBUFS)
624 m->m_pkthdr.csum_flags &=
634 error = checksum_ipv4(
priv, m, pullup_len);
638 else if (error == ENOBUFS)
645 error = checksum_ipv6(
priv, m, pullup_len);
649 else if (error == ENOBUFS)
654 m->m_pkthdr.csum_flags &=
669 if (hook ==
priv->in) {
672 }
else if (hook ==
priv->out &&
priv->in) {
703 free(
priv->conf, M_NETGRAPH);
705 free(
priv, M_NETGRAPH);
717 if (hook ==
priv->in)
720 if (hook ==
priv->out)
#define NG_HOOK_NODE(hook)
int ng_rcvmsg_t(node_p node, item_p item, hook_p lasthook)
int ng_disconnect_t(hook_p hook)
#define NG_NODE_SET_PRIVATE(node, val)
#define NG_RESPOND_MSG(error, here, item, resp)
#define NG_NODE_IS_VALID(node)
#define NG_NODE_UNREF(node)
int ng_rmnode_self(node_p here)
#define NG_FWD_NEW_DATA(error, item, hook, m)
int ng_rcvdata_t(hook_p hook, item_p item)
int ng_shutdown_t(node_p node)
#define NG_FREE_ITEM(item)
int ng_constructor_t(node_p node)
#define NG_NODE_NUMHOOKS(node)
#define NGI_GET_MSG(i, m)
#define NG_NODE_PRIVATE(node)
int ng_newhook_t(node_p node, hook_p hook, const char *name)
static const struct ng_parse_struct_field ng_checksum_stats_fields[]
static ng_shutdown_t ng_checksum_shutdown
static const struct ng_parse_struct_field ng_checksum_config_type_fields[]
static const struct ng_cmdlist ng_checksum_cmdlist[]
static ng_disconnect_t ng_checksum_disconnect
static const struct ng_parse_type ng_checksum_stats_type
static ng_newhook_t ng_checksum_newhook
static struct ng_type typestruct
#define PULLUP_CHECK(mbuf, length)
static ng_rcvmsg_t ng_checksum_rcvmsg
static const struct ng_parse_type ng_checksum_config_type
NETGRAPH_INIT(checksum, &typestruct)
static ng_constructor_t ng_checksum_constructor
static ng_rcvdata_t ng_checksum_rcvdata
struct ng_checksum_priv * priv_p
#define NG_CHECKSUM_NODE_TYPE
#define NG_CHECKSUM_HOOK_OUT
#define NG_CHECKSUM_CSUM_IPV6
#define NG_CHECKSUM_HOOK_IN
@ NGM_CHECKSUM_GETCLR_STATS
#define NG_CHECKSUM_STATS_TYPE
#define NG_CHECKSUM_CSUM_IPV4
#define NGM_CHECKSUM_COOKIE
#define NG_CHECKSUM_CONFIG_TYPE
#define NG_MKRESPONSE(rsp, msg, len, how)
const struct ng_parse_type ng_parse_struct_type
const struct ng_parse_type ng_parse_uint8_type
struct ng_checksum_config * conf
struct ng_mesg::ng_msghdr header