This file is indexed.

/usr/src/xtables-addons-2.10/extensions/xt_DHCPMAC.c is in xtables-addons-dkms 2.10-1build1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*
 *	"DHCPMAC" extensions for Xtables
 *	Copyright © Jan Engelhardt, 2008
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License; either
 *	version 2 of the License, or any later version, as published by the
 *	Free Software Foundation.
 */
#include <linux/ip.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/types.h>
#include <linux/udp.h>
#include <net/ip.h>
#include <linux/netfilter/x_tables.h>
#include "xt_DHCPMAC.h"
#include "compat_xtables.h"

struct dhcp_message {
	uint8_t op, htype, hlen, hops;
	__be32 xid;
	__be16 secs, flags;
	__be32 ciaddr, yiaddr, siaddr, giaddr;
	char chaddr[16];
	/* Omitting all unneeded fields saves runtime memory */
	/* char sname[64], file[128]; */
};

static void ether_set(unsigned char *addr, const unsigned char *op,
    uint8_t mask)
{
	uint8_t lo_mask;
	unsigned int i;

	for (i = 0; i < ETH_ALEN && mask > 0; ++i) {
		lo_mask = (mask >= 8) ? 8 : mask;
		/* FF << 4 >> 4 = 0F */
		lo_mask = (uint8_t)(~0U << lo_mask) >> lo_mask;
		addr[i] &= lo_mask;
		addr[i] |= op[i] & ~lo_mask;
		if (mask >= 8)
			mask -= 8;
		else
			mask = 0;
	}
}

static bool ether_cmp(const unsigned char *lh, const unsigned char *rh,
    uint8_t mask)
{
	uint8_t lo_mask;
	unsigned int i;
#define ZMAC_FMT "%02X:%02X:%02X:%02X:%02X:%02X"
#define ZMACHEX(s) s[0], s[1], s[2], s[3], s[4], s[5]

	for (i = 0; i < ETH_ALEN && mask > 0; ++i) {
		lo_mask = (mask >= 8) ? 8 : mask;
		/* ~(0xFF << 4 >> 4) = ~0x0F = 0xF0 */
		lo_mask = ~((uint8_t)(~0U << lo_mask) >> lo_mask);
		if ((lh[i] ^ rh[i]) & lo_mask)
			return false;
		if (mask >= 8)
			mask -= 8;
		else
			mask = 0;
	}
	return true;
}

static bool
dhcpmac_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
	const struct dhcpmac_info *info = par->matchinfo;
	const struct dhcp_message *dh;
	struct dhcp_message dhcpbuf;

	dh = skb_header_pointer(skb, par->thoff + sizeof(struct udphdr),
	     sizeof(dhcpbuf), &dhcpbuf);
	if (dh == NULL)
		/*
		 * No hotdrop. This packet does not look like DHCP, but other
		 * matches may still have a valid reason to get their chance
		 * to match on this.
		 */
		return false;

	return ether_cmp((const void *)dh->chaddr, info->addr, info->mask);
}

static unsigned int
dhcpmac_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
	const struct dhcpmac_info *info = par->targinfo;
	struct dhcp_message dhcpbuf, *dh;
	struct udphdr udpbuf, *udph;
	unsigned int i;

	if (!skb_make_writable(skb, 0))
		return NF_DROP;

	udph = skb_header_pointer(skb, ip_hdrlen(skb),
	       sizeof(udpbuf), &udpbuf);
	if (udph == NULL)
		return NF_DROP;

	dh = skb_header_pointer(skb, ip_hdrlen(skb) + sizeof(udpbuf),
	     sizeof(dhcpbuf), &dhcpbuf);
	if (dh == NULL)
		return NF_DROP;

	for (i = 0; i < sizeof(dh->chaddr); i += 2)
		csum_replace2(&udph->check, *(const __be16 *)(dh->chaddr + i), 0);

	ether_set(dh->chaddr, info->addr, info->mask);

	for (i = 0; i < sizeof(dh->chaddr); i += 2)
		csum_replace2(&udph->check, 0, *(const __be16 *)(dh->chaddr + i));

	return XT_CONTINUE;
}

static struct xt_target dhcpmac_tg_reg __read_mostly = {
	.name       = "DHCPMAC",
	.revision   = 0,
	.family     = NFPROTO_IPV4,
	.proto      = IPPROTO_UDP,
	.table      = "mangle",
	.target     = dhcpmac_tg,
	.targetsize = XT_ALIGN(sizeof(struct dhcpmac_info)),
	.me         = THIS_MODULE,
};

static struct xt_match dhcpmac_mt_reg __read_mostly = {
	.name       = "dhcpmac",
	.revision   = 0,
	.family     = NFPROTO_IPV4,
	.proto      = IPPROTO_UDP,
	.match      = dhcpmac_mt,
	.matchsize  = sizeof(struct dhcpmac_info),
	.me         = THIS_MODULE,
};

static int __init dhcpmac_init(void)
{
	int ret;

	ret = xt_register_target(&dhcpmac_tg_reg);
	if (ret != 0)
		return ret;
	ret = xt_register_match(&dhcpmac_mt_reg);
	if (ret != 0) {
		xt_unregister_target(&dhcpmac_tg_reg);
		return ret;
	}
	return 0;
}

static void __exit dhcpmac_exit(void)
{
	xt_unregister_target(&dhcpmac_tg_reg);
	xt_unregister_match(&dhcpmac_mt_reg);
}

module_init(dhcpmac_init);
module_exit(dhcpmac_exit);
MODULE_DESCRIPTION("Xtables: Clamp DHCP MAC to packet MAC addresses");
MODULE_AUTHOR("Jan Engelhardt ");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_DHCPMAC");
MODULE_ALIAS("ipt_dhcpmac");