buildSkbIPFilterCondition creates an if-statement to filter by IP inside kfree_skb body. This is used instead of a pre-filter because we need to parse the skb to get the IPs. SECURITY: IPs are converted to hex integers - no string interpolation of user input. IMPORTANT: $saddr_raw/$daddr_raw come f
()
| 619 | // byte order before comparing with the big-endian hex constants from ipToHex(). |
| 620 | // This mirrors how $skb->protocol is handled: bswap($protocol) != 0x0800. |
| 621 | func (g *ScriptGenerator) buildSkbIPFilterCondition() string { |
| 622 | if len(g.config.FilterIPs) == 0 && len(g.config.FilterCIDRs) == 0 { |
| 623 | return "" // No filter |
| 624 | } |
| 625 | |
| 626 | var conditions []string |
| 627 | |
| 628 | // Add IP filters - compare against the raw uint32 IP values |
| 629 | // bswap() converts $saddr_raw from host byte order to network byte order |
| 630 | for _, ip := range g.config.FilterIPs { |
| 631 | ipv4 := ip.To4() |
| 632 | if ipv4 == nil { |
| 633 | continue |
| 634 | } |
| 635 | ipHex := ipToHex(ipv4) |
| 636 | // Match either source or destination (bswap to network byte order first) |
| 637 | conditions = append(conditions, fmt.Sprintf("(bswap($saddr_raw) == 0x%08x || bswap($daddr_raw) == 0x%08x)", ipHex, ipHex)) |
| 638 | } |
| 639 | |
| 640 | // Add CIDR filters - mask and compare |
| 641 | // bswap() converts to network byte order before masking |
| 642 | for _, cidr := range g.config.FilterCIDRs { |
| 643 | if cidr == nil { |
| 644 | continue |
| 645 | } |
| 646 | ipv4 := cidr.IP.To4() |
| 647 | if ipv4 == nil { |
| 648 | continue |
| 649 | } |
| 650 | networkHex := ipToHex(ipv4) |
| 651 | maskHex := ipToHex(net.IP(cidr.Mask).To4()) |
| 652 | conditions = append(conditions, fmt.Sprintf("((bswap($saddr_raw) & 0x%08x) == 0x%08x || (bswap($daddr_raw) & 0x%08x) == 0x%08x)", |
| 653 | maskHex, networkHex, maskHex, networkHex)) |
| 654 | } |
| 655 | |
| 656 | if len(conditions) == 0 { |
| 657 | return "" |
| 658 | } |
| 659 | |
| 660 | // Generate an if-statement that returns early if no condition matches |
| 661 | combined := strings.Join(conditions, " || ") |
| 662 | return fmt.Sprintf(" // IP/CIDR filter: skip if not matching\n if (!(%s)) { return; }\n\n", combined) |
| 663 | } |
| 664 | |
| 665 | // ipToHex converts an IPv4 address to a uint32 in network byte order. |
| 666 | // SECURITY: This function only outputs hex digits - no user input passes through. |