static int nfattr_to_tcp(struct nfattr *cda[], struct nf_conn *ct) { struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1]; struct nfattr *tb[CTA_PROTOINFO_TCP_MAX]; /* updates could not contain anything about the private * protocol info, in that case skip the parsing */ if (!attr) return 0; nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr); if (nfattr_bad_size(tb, CTA_PROTOINFO_TCP_MAX, cta_min_tcp)) return -EINVAL; if (!tb[CTA_PROTOINFO_TCP_STATE-1]) return -EINVAL; write_lock_bh(&tcp_lock); ct->proto.tcp.state = *(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_TCP_STATE-1]); write_unlock_bh(&tcp_lock); return 0; }
static int ipv4_nfattr_to_tuple(struct nfattr *tb[], struct nf_conntrack_tuple *t) { if (!tb[CTA_IP_V4_SRC-1] || !tb[CTA_IP_V4_DST-1]) return -EINVAL; if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip)) return -EINVAL; t->src.u3.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_SRC-1]); t->dst.u3.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_DST-1]); return 0; }
static int ipv6_nfattr_to_tuple(struct nfattr *tb[], struct nf_conntrack_tuple *t) { if (!tb[CTA_IP_V6_SRC-1] || !tb[CTA_IP_V6_DST-1]) return -EINVAL; if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip)) return -EINVAL; memcpy(&t->src.u3.ip6, NFA_DATA(tb[CTA_IP_V6_SRC-1]), sizeof(u_int32_t) * 4); memcpy(&t->dst.u3.ip6, NFA_DATA(tb[CTA_IP_V6_DST-1]), sizeof(u_int32_t) * 4); return 0; }
static int icmp_nfattr_to_tuple(struct nfattr *tb[], struct nf_conntrack_tuple *tuple) { if (!tb[CTA_PROTO_ICMP_TYPE-1] || !tb[CTA_PROTO_ICMP_CODE-1] || !tb[CTA_PROTO_ICMP_ID-1]) return -EINVAL; if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto)) return -EINVAL; tuple->dst.u.icmp.type = *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_TYPE-1]); tuple->dst.u.icmp.code = *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]); tuple->src.u.icmp.id = *(__be16 *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]); if (tuple->dst.u.icmp.type >= sizeof(invmap) || !invmap[tuple->dst.u.icmp.type]) return -EINVAL; return 0; }