File: l2tp-dhcp-inform

package info (click to toggle)
libnet-dhcp-perl 0.696%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, stretch
  • size: 328 kB
  • ctags: 63
  • sloc: perl: 1,964; sh: 51; makefile: 8
file content (108 lines) | stat: -rw-r--r-- 2,499 bytes parent folder | download | duplicates (3)
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
#!/usr/bin/perl

# TODO
# * use syslog
# * runit - as also invalid DHCP packets cause library to croak()
# * error checking

use strict;
use warnings;

use Sys::Hostname;
use IO::Socket::INET;
use Net::DHCP::Constants qw/:dho_codes :dhcp_message :bootp_codes :htype_codes :dhcp_other/;
use Net::DHCP::Packet;

# populated in BEGIN
my %addOption;
my $domainnameservers = '192.0.1.2 192.0.1.50';
# Mac OS X 10.7 seems to accept space seperated entries here (no idea if others do too)
my $domainname = 'domain.foo';
my @subnets;
for (<DATA>) {
	next if (/^(#|$)/);

	chomp;
	push @subnets, $_;
}

my $sock = IO::Socket::INET->new(
	Proto		=> 'udp',
	LocalPort	=> 67,
);
unless ($sock) {
	print STDERR "unable to open socket: $@\n";
	exit 1;
}

my $buf;
while (my $src = $sock->recv($buf, DHCP_MAX_MTU - DHCP_UDP_OVERHEAD)) {
	my $sport = $sock->peerport;
	next unless ($sport == 68);

	# add padding to stop the library complaining
	# as the packets are typically 262 bytes long
	$buf .= "\x00" x (BOOTP_MIN_LEN() - length($buf))
		if (length($buf) < BOOTP_MIN_LEN());

	my $pac = Net::DHCP::Packet->new($buf);
	next unless ($pac->isDhcp
		&& $pac->op == BOOTREQUEST()
		&& $pac->htype == HTYPE_FDDI()
		&& $pac->getOptionValue(DHO_DHCP_MESSAGE_TYPE()) == DHCPINFORM());

	my $res = Net::DHCP::Packet->new(
		Op			=> BOOTREPLY(),
		Htype			=> $pac->htype,
		Xid			=> $pac->xid,
		Ciaddr			=> $sock->peerhost,
		Chaddr			=> $pac->chaddr,
		Sname			=> hostname,

		DHO_DHCP_MESSAGE_TYPE()	=> DHCPACK(),
	);

	foreach (split / /, $pac->getOptionValue(DHO_DHCP_PARAMETER_REQUEST_LIST())) {
		&{$addOption{$_}}($res, $_)
			if (defined($addOption{$_}));
	}

	$sock->send($res->serialize);
}

exit 0;

BEGIN {
	sub OptionSubnetMask {
		my ($res, $opt) = @_;

		$res->addOptionValue(DHO_SUBNET_MASK(), '255.255.255.255');
	}
	$addOption{DHO_SUBNET_MASK()} = \&OptionSubnetMask;

	sub OptionDomainName {
		my ($res, $opt) = @_;

		$res->addOptionValue(DHO_DOMAIN_NAME(), $domainname);
	}
	$addOption{DHO_DOMAIN_NAME()} = \&OptionDomainName;

	sub OptionDomainNameServers {
		my ($res, $opt) = @_;

		$res->addOptionValue(DHO_DOMAIN_NAME_SERVERS(), $domainnameservers);
	}
	$addOption{DHO_DOMAIN_NAME_SERVERS()} = \&OptionDomainNameServers;

	sub OptionClasslessStaticRoutes {
		my ($res, $opt) = @_;

		$res->addOptionValue($opt, [ map { [$_, '0.0.0.0'] } @subnets ]);
	}
	$addOption{121} = \&OptionClasslessStaticRoutes;
	$addOption{249} = \&OptionClasslessStaticRoutes;
}

__DATA__
10.0.0.0/8
192.168.0.0/16