* Re: AW: Add new target in mangle table
[not found] <20080414071710.C0E061802C4D8@sovereign.computergmbh.de>
@ 2008-04-14 10:20 ` Jan Engelhardt
2008-04-14 15:44 ` manuprivat
2008-04-14 16:27 ` Jan Engelhardt
1 sibling, 1 reply; 12+ messages in thread
From: Jan Engelhardt @ 2008-04-14 10:20 UTC (permalink / raw)
To: Manuel Scheub; +Cc: netfilter-devel
On Monday 2008-04-14 09:10, Manuel Scheub wrote:
>
>>>Hi developers,
>>>
>>>I encountered difficulties during integrating a new target in mangle
>>>table (iptables-1.4.0 (from www.netfilter.org), kernel-2.6.23 (from
>>>www.kernel.org)).
>>>I have a master from iptables-1.2.9 and kernel-2.6.3. But there were too
>>>many differences and changes be made.
>>>The idea behind to add the target is, that a user who has a fix-ip entry
>>>in his network settings can be handled from a gateway, for which the new
>>>targets should be implemented. for example:
>>>
>>># iptables -t mangle -I PREROUTING -i eth2 -s 192.168.0.168 -j SADDR
>>>--to-source 10.0.19.2
>>
>>This looks pretty much like RAWNAT, as posted in
>>http://marc.info/?l=netfilter-devel&m=120024054521550&w=2 .
>>
>Excuse me, but I didn?t get the solution for the RAWNAT issue.
>Maybe it refers to that I'm not so familiar with the netfilter stuff.
>
>Is it possible to realize my issue, or do I have problems with the
>conntrack?
Could you describe the target a bit closer? I did not quite get what you
mean by "user who has a fixed IP address can be handled(?) from [by?] a
gateway". Because your code (SADDR) does seem to only change the source
address, I guessed it is equivalent to RAWSNAT.
>Where can I find the source code for the RAWNAT target.
It is in a git repository at
http://dev.computergmbh.de/gitweb.cgi?p=xtables-addons (there is also
the git:// URL for cloning), and http://tinyurl.com/4qoylk would give
you a snapshot in tar format.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: AW: Add new target in mangle table
2008-04-14 10:20 ` AW: Add new target in mangle table Jan Engelhardt
@ 2008-04-14 15:44 ` manuprivat
0 siblings, 0 replies; 12+ messages in thread
From: manuprivat @ 2008-04-14 15:44 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: netfilter-devel
> >>>Hi developers,
> >>>
> >>>I encountered difficulties during integrating a new target in mangle
> >>>table (iptables-1.4.0 (from www.netfilter.org), kernel-2.6.23 (from
> >>>www.kernel.org)).
> >>>I have a master from iptables-1.2.9 and kernel-2.6.3. But there were
> too
> >>>many differences and changes be made.
> >>>The idea behind to add the target is, that a user who has a fix-ip
> entry
> >>>in his network settings can be handled from a gateway, for which the
> new
> >>>targets should be implemented. for example:
> >>>
> >>># iptables -t mangle -I PREROUTING -i eth2 -s 192.168.0.168 -j SADDR
> >>>--to-source 10.0.19.2
> >>
> >>This looks pretty much like RAWNAT, as posted in
> >>http://marc.info/?l=netfilter-devel&m=120024054521550&w=2 .
> >>
> >Excuse me, but I didn?t get the solution for the RAWNAT issue.
> >Maybe it refers to that I'm not so familiar with the netfilter stuff.
> >
> >Is it possible to realize my issue, or do I have problems with the
> >conntrack?
>
> Could you describe the target a bit closer? I did not quite get what you
> mean by "user who has a fixed IP address can be handled(?) from [by?] a
> gateway". Because your code (SADDR) does seem to only change the source
> address, I guessed it is equivalent to RAWSNAT.
>
>
>
> >Where can I find the source code for the RAWNAT target.
>
> It is in a git repository at
> http://dev.computergmbh.de/gitweb.cgi?p=xtables-addons (there is also
> the git:// URL for cloning), and http://tinyurl.com/4qoylk would give
> you a snapshot in tar format.
yes, i think it is equivalent to RAWSNAT and RAWDNAT. I'll try to solve the problem with the RAWNAT target. Thank you very much.
"user who has a fixed IP address can be handled(?) from [by?] a gateway"
Sorry for the imprecise information. The issue is that I have a gateway (normal pc with 2 NICs, LAN1=WAN, LAN2=internal NET) where users can get an access to the internet. The gateway has a self made user management implemented. All the users in the internal net are handled with IPs
gateway:10.0.2.1<->user-dhcp-lease:10.0.2.2, gateway:10.0.3.1<->user-dhcp-lease:10.0.3.2,... and so on.
If a user has an fix-ip entry in his notebook, actually it's not possible to communicate with. For this issue I need a feature which i call ip-plug'n'play. Somewhere in the raw or mangle table I would like to change the source/destination address for the internal user management of the gateway. hope, it's a bit clearer now.
--
Psst! Geheimtipp: Online Games kostenlos spielen bei den GMX Free Games!
http://games.entertainment.gmx.net/de/entertainment/games/free
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: AW: Add new target in mangle table
[not found] <20080414071710.C0E061802C4D8@sovereign.computergmbh.de>
2008-04-14 10:20 ` AW: Add new target in mangle table Jan Engelhardt
@ 2008-04-14 16:27 ` Jan Engelhardt
2008-04-14 16:34 ` manuprivat
1 sibling, 1 reply; 12+ messages in thread
From: Jan Engelhardt @ 2008-04-14 16:27 UTC (permalink / raw)
To: Manuel Scheub; +Cc: netfilter-devel
On Monday 2008-04-14 09:10, Manuel Scheub wrote:
>>
>># iptables -t mangle -I PREROUTING -i eth2 -s 192.168.0.168 -j SADDR
>>--to-source 10.0.19.2
>
One question this throws up... how do you know the address is 192.168.0.168?
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: AW: Add new target in mangle table
2008-04-14 16:27 ` Jan Engelhardt
@ 2008-04-14 16:34 ` manuprivat
2008-04-14 16:58 ` Jan Engelhardt
0 siblings, 1 reply; 12+ messages in thread
From: manuprivat @ 2008-04-14 16:34 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: netfilter-devel
> >>
> >># iptables -t mangle -I PREROUTING -i eth2 -s 192.168.0.168 -j SADDR
> >>--to-source 10.0.19.2
> >
> One question this throws up... how do you know the address is
> 192.168.0.168?
Actually, I dont know that! It is only an example to show the different IP-ranges. Excuse my improper representation.
--
Psst! Geheimtipp: Online Games kostenlos spielen bei den GMX Free Games!
http://games.entertainment.gmx.net/de/entertainment/games/free
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: AW: Add new target in mangle table
2008-04-14 16:34 ` manuprivat
@ 2008-04-14 16:58 ` Jan Engelhardt
2008-04-15 8:06 ` Manu
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Jan Engelhardt @ 2008-04-14 16:58 UTC (permalink / raw)
To: manuprivat; +Cc: netfilter-devel
On Monday 2008-04-14 18:34, manu wrote:
>> >>
>> >># iptables -t mangle -I PREROUTING -i eth2 -s 192.168.0.168 -j SADDR
>> >>--to-source 10.0.19.2
>> >
>> One question this throws up... how do you know the address is
>> 192.168.0.168?
>
>Actually, I dont know that! It is only an example to show the different
>IP-ranges. Excuse my improper representation.
The question is more of a technical one-- if you do not know the
source address the client will be using, how can you reliably
mangle the address?
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: AW: Add new target in mangle table
2008-04-14 16:58 ` Jan Engelhardt
@ 2008-04-15 8:06 ` Manu
2008-04-15 8:10 ` Manu
2008-04-15 8:35 ` manuprivat
2 siblings, 0 replies; 12+ messages in thread
From: Manu @ 2008-04-15 8:06 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: netfilter-devel
[-- Attachment #1: Type: text/plain, Size: 642 bytes --]
> >> >>
> >> >># iptables -t mangle -I PREROUTING -i eth2 -s 192.168.0.168 -j SADDR
> >> >>--to-source 10.0.19.2
> >> >
> >> One question this throws up... how do you know the address is
> >> 192.168.0.168?
> >
> >Actually, I dont know that! It is only an example to show the different
> >IP-ranges. Excuse my improper representation.
>
> The question is more of a technical one-- if you do not know the
> source address the client will be using, how can you reliably
> mangle the address?
I modified the udhcpd from the busybox - have a look in the attached
file.
To handle the different cases i wrote a shell script - also attached.
[-- Attachment #2: dhcpd.sh --]
[-- Type: application/x-shellscript, Size: 8392 bytes --]
[-- Attachment #3: dhcpd.c --]
[-- Type: text/x-csrc, Size: 12170 bytes --]
/* dhcpd.c
*
* udhcp Server
* Copyright (C) 1999 Matthew Ramsay <matthewr@moreton.com.au>
* Chris Trew <ctrew@moreton.com.au>
*
* Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <time.h>
#include <sys/time.h>
#include <netpacket/packet.h>
#include "dhcpd.h"
#include "arpping.h"
#include "socket.h"
#include "options.h"
#include "files.h"
#include "serverpacket.h"
#include "common.h"
#include "signalpipe.h"
/* globals */
struct dhcpOfferedAddr *leases;
struct server_config_t server_config;
#ifdef COMBINED_BINARY
int udhcpd_main(int argc, char *argv[])
#else
int main(int argc, char *argv[])
#endif
{
fd_set rfds;
fd_set thefds;
struct timeval tv;
int bytes, retval;
struct dhcpMessage packet;
uint8_t *state;
uint8_t *server_id, *requested;
uint32_t server_id_align, requested_align;
unsigned long timeout_end;
struct option_set *option;
struct dhcpOfferedAddr *lease;
int max_sock = 0;
unsigned long num_ips;
char buffer[100];
char *pname;
int i;
int lastindex = 0;
memset(&server_config, 0, sizeof(struct server_config_t));
read_config(argc < 2 ? DHCPD_CONF_FILE : argv[1]);
/* Start the log, sanitize fd's, and write a pid file */
start_log_and_pid("udhcpd", server_config.pidfile);
if ((option = find_option(server_config.options, DHCP_LEASE_TIME))) {
memcpy(&server_config.lease, option->data + 2, 4);
server_config.lease = ntohl(server_config.lease);
}
else server_config.lease = LEASE_TIME;
/* Sanity check */
server_config.end = ntohl(server_config.start);
server_config.end = htonl(server_config.end + (server_config.max_leases - 1) * server_config.offset);
num_ips = (ntohl(server_config.end) - ntohl(server_config.start)) / server_config.offset + 1;
if (server_config.max_leases > num_ips) {
LOG(LOG_ERR, "max_leases value (%lu) not sane, "
"setting to %lu instead",
server_config.max_leases, num_ips);
server_config.max_leases = num_ips;
}
leases = xcalloc(server_config.max_leases, sizeof(struct dhcpOfferedAddr));
read_leases(server_config.lease_file);
server_config.numofinterfaces = 0;
pname = strtok(server_config.interfaces, " ");
while (pname) {
server_config.ifname[server_config.numofinterfaces] = pname;
server_config.fds[server_config.numofinterfaces] = -1;
server_config.arpfds[server_config.numofinterfaces] = -1;
if (read_interface(server_config.ifname[server_config.numofinterfaces],
&server_config.ifindex[server_config.numofinterfaces],
&server_config.server[server_config.numofinterfaces],
server_config.arp[server_config.numofinterfaces]) < 0)
return 1;
server_config.numofinterfaces++;
pname = strtok(0, " ");
}
server_config.currentinterface = 0;
/* #ifndef UDHCP_DEBUG */
background(server_config.pidfile); /* hold lock during fork. */
/* #endif */
FD_ZERO(&thefds);
FD_ZERO(&rfds);
/* Setup the signal pipe */
udhcp_sp_setup();
timeout_end = time(0) + server_config.auto_time;
while(1) { /* loop until universe collapses */
for (i = 0; i < server_config.numofinterfaces; i++) {
if (server_config.fds[i] < 0)
if ((server_config.fds[i] = listen_socket(INADDR_ANY, SERVER_PORT,
server_config.ifname[i])) < 0) {
LOG(LOG_ERR, "FATAL: couldn't create server socket, %m");
return 2;
}
if (server_config.ippnp) {
if (server_config.arpfds[i] < 0) {
if ((server_config.arpfds[i] =
arp_socket(server_config.ifname[i], server_config.ifindex[i])) < 0) {
LOG(LOG_ERR, "FATAL: couldn't create arp socket, %m");
return 2;
}
}
}
max_sock = udhcp_sp_fd_set(&thefds, server_config.fds[i]);
if (server_config.ippnp) {
max_sock = udhcp_sp_fd_set(&thefds, server_config.arpfds[i]);
}
}
if (server_config.auto_time) {
tv.tv_sec = timeout_end - time(0);
tv.tv_usec = 0;
}
memcpy(&rfds, &thefds, sizeof(fd_set));
if (!server_config.auto_time || tv.tv_sec > 0) {
retval = select(max_sock + 1, &rfds, NULL, NULL,
server_config.auto_time ? &tv : NULL);
} else retval = 0; /* If we already timed out, fall through */
if (retval == 0) {
write_leases();
timeout_end = time(0) + server_config.auto_time;
continue;
} else if (retval < 0 && errno != EINTR) {
DEBUG(LOG_INFO, "error on select");
continue;
}
switch (udhcp_sp_read(&rfds)) {
case SIGUSR1:
LOG(LOG_INFO, "Received a SIGUSR1");
write_leases();
/* why not just reset the timeout, eh */
timeout_end = time(0) + server_config.auto_time;
continue;
case SIGTERM:
LOG(LOG_INFO, "Received a SIGTERM");
write_leases();
return 0;
case 0: break; /* no signal */
default: continue; /* signal or error (probably EINTR) */
}
for (i = lastindex; i < (server_config.numofinterfaces * 2); i++) {
if (FD_ISSET(server_config.fds[i % server_config.numofinterfaces], &rfds)) {
server_config.currentinterface = i % server_config.numofinterfaces;
lastindex = server_config.currentinterface + 1;
break;
}
if (server_config.ippnp) {
if (FD_ISSET(server_config.arpfds[i % server_config.numofinterfaces], &rfds)) {
server_config.currentinterface = i % server_config.numofinterfaces;
lastindex = server_config.currentinterface + 1;
break;
}
}
}
if (server_config.ippnp) {
if (FD_ISSET(server_config.arpfds[server_config.currentinterface], &rfds)) {
unsigned char buf[1024];
struct sockaddr_ll sll;
int sll_len = sizeof(sll);
int n;
n = recvfrom(server_config.arpfds[server_config.currentinterface],
buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr*)&sll, &sll_len);
if (n < 0) {
DEBUG(LOG_INFO, "error receiving arp");
}
else {
DEBUG(LOG_INFO, "received arp on %s %d", server_config.ifname[server_config.currentinterface], n);
handleArpPacket(buf);
}
}
}
if (FD_ISSET(server_config.fds[server_config.currentinterface], &rfds)) {
if ((bytes = get_packet(&packet, server_config.fds[server_config.currentinterface])) < 0) {
if (bytes == -1 && errno != EINTR) {
DEBUG(LOG_INFO, "error on read, %m, reopening socket");
close(server_config.fds[server_config.currentinterface]);
max_sock = udhcp_sp_fd_unset(&thefds, server_config.fds[i]);
server_config.fds[server_config.currentinterface] = -1;
}
continue;
}
}
else
continue;
if ((state = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) {
DEBUG(LOG_ERR, "couldn't get option from packet, ignoring");
continue;
}
/* ADDME: look for a static lease */
lease = find_lease_by_chaddr(packet.chaddr);
if (lease && lease->ippnpaddr) { /* The computer with this mac was seen with fixed ip address before */
char buf[256];
sprintf(buf, "ippnpremove %02X:%02X:%02X:%02X:%02X:%02X %d.%d.%d.%d %s",
lease->chaddr[0], lease->chaddr[1], lease->chaddr[2],
lease->chaddr[3], lease->chaddr[4], lease->chaddr[5],
(lease->yiaddr) & 0xff, (lease->yiaddr >> 8) & 0xff,
(lease->yiaddr >> 16) & 0xff, (lease->yiaddr >> 24) & 0xff,
lease->ifname);
system(buf);
}
switch (state[0]) {
case DHCPDISCOVER:
DEBUG(LOG_INFO,"received DISCOVER");
sprintf(buffer, "dhcpd.sh discover %02X:%02X:%02X:%02X:%02X:%02X %s",
packet.chaddr[0], packet.chaddr[1], packet.chaddr[2],
packet.chaddr[3], packet.chaddr[4], packet.chaddr[5], server_config.ifname[server_config.currentinterface]);
if (WEXITSTATUS(system(buffer)) == 0) {
if (sendOffer(&packet) < 0) {
LOG(LOG_ERR, "send OFFER failed");
}
}
break;
case DHCPREQUEST:
DEBUG(LOG_INFO, "received REQUEST");
requested = get_option(&packet, DHCP_REQUESTED_IP);
server_id = get_option(&packet, DHCP_SERVER_ID);
if (requested) memcpy(&requested_align, requested, 4);
if (server_id) memcpy(&server_id_align, server_id, 4);
if (lease) { /*ADDME: or static lease */
sprintf(buffer, "dhcpd.sh dhcprequest %02X:%02X:%02X:%02X:%02X:%02X %d.%d.%d.%d %s",
packet.chaddr[0], packet.chaddr[1], packet.chaddr[2],
packet.chaddr[3], packet.chaddr[4], packet.chaddr[5],
lease->yiaddr & 0xff, (lease->yiaddr >> 8) & 0xff,
(lease->yiaddr >> 16) & 0xff, (lease->yiaddr >> 24) & 0xff,
server_config.ifname[server_config.currentinterface]);
if (server_id) {
/* SELECTING State */
DEBUG(LOG_INFO, "server_id = %08x", ntohl(server_id_align));
if (server_id_align == server_config.server[server_config.currentinterface] && requested &&
requested_align == lease->yiaddr) {
if (WEXITSTATUS(system(buffer)) == 0)
sendACK(&packet, lease->yiaddr);
}
} else {
if (requested) {
/* INIT-REBOOT State */
if (lease->yiaddr == requested_align) {
if (WEXITSTATUS(system(buffer)) == 0)
sendACK(&packet, lease->yiaddr);
}
else sendNAK(&packet);
} else {
/* RENEWING or REBINDING State */
if (lease->yiaddr == packet.ciaddr) {
if (WEXITSTATUS(system(buffer)) == 0)
sendACK(&packet, lease->yiaddr);
}
else {
/* don't know what to do!!!! */
sendNAK(&packet);
}
}
}
/* what to do if we have no record of the client */
} else if (server_id) {
/* SELECTING State */
} else if (requested) {
/* INIT-REBOOT State */
if ((lease = find_lease_by_yiaddr(requested_align))) {
if (lease_expired(lease)) {
/* probably best if we drop this lease */
memset(lease->chaddr, 0, 16);
/* make some contention for this address */
} else sendNAK(&packet);
} else if (requested_align < server_config.start ||
requested_align > server_config.end ||
((requested_align - server_config.start) % server_config.start) == 1) {
sendNAK(&packet);
} /* else remain silent */
} else {
/* RENEWING or REBINDING State */
}
break;
case DHCPDECLINE:
DEBUG(LOG_INFO,"received DECLINE");
if (lease) {
memset(lease->chaddr, 0, 16);
lease->expires = time(0) + server_config.decline_time;
}
break;
case DHCPRELEASE:
DEBUG(LOG_INFO,"received RELEASE");
if (lease) {
sprintf(buffer, "dhcpd.sh release %02X:%02X:%02X:%02X:%02X:%02X %d.%d.%d.%d %s",
packet.chaddr[0], packet.chaddr[1], packet.chaddr[2],
packet.chaddr[3], packet.chaddr[4], packet.chaddr[5],
lease->yiaddr & 0xff, (lease->yiaddr >> 8) & 0xff,
(lease->yiaddr >> 16) & 0xff, (lease->yiaddr >> 24) & 0xff,
server_config.ifname[server_config.currentinterface]);
system(buffer);
lease->expires = time(0);
}
break;
case DHCPINFORM:
DEBUG(LOG_INFO,"received INFORM");
if (lease) {
sprintf(buffer, "dhcpd.sh inform %02X:%02X:%02X:%02X:%02X:%02X %d.%d.%d.%d %s",
packet.chaddr[0], packet.chaddr[1], packet.chaddr[2],
packet.chaddr[3], packet.chaddr[4], packet.chaddr[5],
lease->yiaddr & 0xff, (lease->yiaddr >> 8) & 0xff,
(lease->yiaddr >> 16) & 0xff, (lease->yiaddr >> 24) & 0xff,
server_config.ifname[server_config.currentinterface]);
system(buffer);
send_inform(&packet, lease->yiaddr);
}
break;
default:
LOG(LOG_WARNING, "unsupported DHCP message (%02x) -- ignoring", state[0]);
}
}
return 0;
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: AW: Add new target in mangle table
2008-04-14 16:58 ` Jan Engelhardt
2008-04-15 8:06 ` Manu
@ 2008-04-15 8:10 ` Manu
2008-04-15 8:35 ` manuprivat
2 siblings, 0 replies; 12+ messages in thread
From: Manu @ 2008-04-15 8:10 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: netfilter-devel
[-- Attachment #1: Type: text/plain, Size: 644 bytes --]
> >> >>
> >> >># iptables -t mangle -I PREROUTING -i eth2 -s 192.168.0.168 -j SADDR
> >> >>--to-source 10.0.19.2
> >> >
> >> One question this throws up... how do you know the address is
> >> 192.168.0.168?
> >
> >Actually, I dont know that! It is only an example to show the different
> >IP-ranges. Excuse my improper representation.
>
> The question is more of a technical one-- if you do not know the
> source address the client will be using, how can you reliably
> mangle the address?
> --
I modified the udhcpd from the busybox - have a look in the attached
file.
To handle the different cases i wrote a shell script - also attached.
[-- Attachment #2: dhcpd.sh --]
[-- Type: application/x-shellscript, Size: 8392 bytes --]
[-- Attachment #3: dhcpd.c --]
[-- Type: text/x-csrc, Size: 12170 bytes --]
/* dhcpd.c
*
* udhcp Server
* Copyright (C) 1999 Matthew Ramsay <matthewr@moreton.com.au>
* Chris Trew <ctrew@moreton.com.au>
*
* Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <time.h>
#include <sys/time.h>
#include <netpacket/packet.h>
#include "dhcpd.h"
#include "arpping.h"
#include "socket.h"
#include "options.h"
#include "files.h"
#include "serverpacket.h"
#include "common.h"
#include "signalpipe.h"
/* globals */
struct dhcpOfferedAddr *leases;
struct server_config_t server_config;
#ifdef COMBINED_BINARY
int udhcpd_main(int argc, char *argv[])
#else
int main(int argc, char *argv[])
#endif
{
fd_set rfds;
fd_set thefds;
struct timeval tv;
int bytes, retval;
struct dhcpMessage packet;
uint8_t *state;
uint8_t *server_id, *requested;
uint32_t server_id_align, requested_align;
unsigned long timeout_end;
struct option_set *option;
struct dhcpOfferedAddr *lease;
int max_sock = 0;
unsigned long num_ips;
char buffer[100];
char *pname;
int i;
int lastindex = 0;
memset(&server_config, 0, sizeof(struct server_config_t));
read_config(argc < 2 ? DHCPD_CONF_FILE : argv[1]);
/* Start the log, sanitize fd's, and write a pid file */
start_log_and_pid("udhcpd", server_config.pidfile);
if ((option = find_option(server_config.options, DHCP_LEASE_TIME))) {
memcpy(&server_config.lease, option->data + 2, 4);
server_config.lease = ntohl(server_config.lease);
}
else server_config.lease = LEASE_TIME;
/* Sanity check */
server_config.end = ntohl(server_config.start);
server_config.end = htonl(server_config.end + (server_config.max_leases - 1) * server_config.offset);
num_ips = (ntohl(server_config.end) - ntohl(server_config.start)) / server_config.offset + 1;
if (server_config.max_leases > num_ips) {
LOG(LOG_ERR, "max_leases value (%lu) not sane, "
"setting to %lu instead",
server_config.max_leases, num_ips);
server_config.max_leases = num_ips;
}
leases = xcalloc(server_config.max_leases, sizeof(struct dhcpOfferedAddr));
read_leases(server_config.lease_file);
server_config.numofinterfaces = 0;
pname = strtok(server_config.interfaces, " ");
while (pname) {
server_config.ifname[server_config.numofinterfaces] = pname;
server_config.fds[server_config.numofinterfaces] = -1;
server_config.arpfds[server_config.numofinterfaces] = -1;
if (read_interface(server_config.ifname[server_config.numofinterfaces],
&server_config.ifindex[server_config.numofinterfaces],
&server_config.server[server_config.numofinterfaces],
server_config.arp[server_config.numofinterfaces]) < 0)
return 1;
server_config.numofinterfaces++;
pname = strtok(0, " ");
}
server_config.currentinterface = 0;
/* #ifndef UDHCP_DEBUG */
background(server_config.pidfile); /* hold lock during fork. */
/* #endif */
FD_ZERO(&thefds);
FD_ZERO(&rfds);
/* Setup the signal pipe */
udhcp_sp_setup();
timeout_end = time(0) + server_config.auto_time;
while(1) { /* loop until universe collapses */
for (i = 0; i < server_config.numofinterfaces; i++) {
if (server_config.fds[i] < 0)
if ((server_config.fds[i] = listen_socket(INADDR_ANY, SERVER_PORT,
server_config.ifname[i])) < 0) {
LOG(LOG_ERR, "FATAL: couldn't create server socket, %m");
return 2;
}
if (server_config.ippnp) {
if (server_config.arpfds[i] < 0) {
if ((server_config.arpfds[i] =
arp_socket(server_config.ifname[i], server_config.ifindex[i])) < 0) {
LOG(LOG_ERR, "FATAL: couldn't create arp socket, %m");
return 2;
}
}
}
max_sock = udhcp_sp_fd_set(&thefds, server_config.fds[i]);
if (server_config.ippnp) {
max_sock = udhcp_sp_fd_set(&thefds, server_config.arpfds[i]);
}
}
if (server_config.auto_time) {
tv.tv_sec = timeout_end - time(0);
tv.tv_usec = 0;
}
memcpy(&rfds, &thefds, sizeof(fd_set));
if (!server_config.auto_time || tv.tv_sec > 0) {
retval = select(max_sock + 1, &rfds, NULL, NULL,
server_config.auto_time ? &tv : NULL);
} else retval = 0; /* If we already timed out, fall through */
if (retval == 0) {
write_leases();
timeout_end = time(0) + server_config.auto_time;
continue;
} else if (retval < 0 && errno != EINTR) {
DEBUG(LOG_INFO, "error on select");
continue;
}
switch (udhcp_sp_read(&rfds)) {
case SIGUSR1:
LOG(LOG_INFO, "Received a SIGUSR1");
write_leases();
/* why not just reset the timeout, eh */
timeout_end = time(0) + server_config.auto_time;
continue;
case SIGTERM:
LOG(LOG_INFO, "Received a SIGTERM");
write_leases();
return 0;
case 0: break; /* no signal */
default: continue; /* signal or error (probably EINTR) */
}
for (i = lastindex; i < (server_config.numofinterfaces * 2); i++) {
if (FD_ISSET(server_config.fds[i % server_config.numofinterfaces], &rfds)) {
server_config.currentinterface = i % server_config.numofinterfaces;
lastindex = server_config.currentinterface + 1;
break;
}
if (server_config.ippnp) {
if (FD_ISSET(server_config.arpfds[i % server_config.numofinterfaces], &rfds)) {
server_config.currentinterface = i % server_config.numofinterfaces;
lastindex = server_config.currentinterface + 1;
break;
}
}
}
if (server_config.ippnp) {
if (FD_ISSET(server_config.arpfds[server_config.currentinterface], &rfds)) {
unsigned char buf[1024];
struct sockaddr_ll sll;
int sll_len = sizeof(sll);
int n;
n = recvfrom(server_config.arpfds[server_config.currentinterface],
buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr*)&sll, &sll_len);
if (n < 0) {
DEBUG(LOG_INFO, "error receiving arp");
}
else {
DEBUG(LOG_INFO, "received arp on %s %d", server_config.ifname[server_config.currentinterface], n);
handleArpPacket(buf);
}
}
}
if (FD_ISSET(server_config.fds[server_config.currentinterface], &rfds)) {
if ((bytes = get_packet(&packet, server_config.fds[server_config.currentinterface])) < 0) {
if (bytes == -1 && errno != EINTR) {
DEBUG(LOG_INFO, "error on read, %m, reopening socket");
close(server_config.fds[server_config.currentinterface]);
max_sock = udhcp_sp_fd_unset(&thefds, server_config.fds[i]);
server_config.fds[server_config.currentinterface] = -1;
}
continue;
}
}
else
continue;
if ((state = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) {
DEBUG(LOG_ERR, "couldn't get option from packet, ignoring");
continue;
}
/* ADDME: look for a static lease */
lease = find_lease_by_chaddr(packet.chaddr);
if (lease && lease->ippnpaddr) { /* The computer with this mac was seen with fixed ip address before */
char buf[256];
sprintf(buf, "ippnpremove %02X:%02X:%02X:%02X:%02X:%02X %d.%d.%d.%d %s",
lease->chaddr[0], lease->chaddr[1], lease->chaddr[2],
lease->chaddr[3], lease->chaddr[4], lease->chaddr[5],
(lease->yiaddr) & 0xff, (lease->yiaddr >> 8) & 0xff,
(lease->yiaddr >> 16) & 0xff, (lease->yiaddr >> 24) & 0xff,
lease->ifname);
system(buf);
}
switch (state[0]) {
case DHCPDISCOVER:
DEBUG(LOG_INFO,"received DISCOVER");
sprintf(buffer, "dhcpd.sh discover %02X:%02X:%02X:%02X:%02X:%02X %s",
packet.chaddr[0], packet.chaddr[1], packet.chaddr[2],
packet.chaddr[3], packet.chaddr[4], packet.chaddr[5], server_config.ifname[server_config.currentinterface]);
if (WEXITSTATUS(system(buffer)) == 0) {
if (sendOffer(&packet) < 0) {
LOG(LOG_ERR, "send OFFER failed");
}
}
break;
case DHCPREQUEST:
DEBUG(LOG_INFO, "received REQUEST");
requested = get_option(&packet, DHCP_REQUESTED_IP);
server_id = get_option(&packet, DHCP_SERVER_ID);
if (requested) memcpy(&requested_align, requested, 4);
if (server_id) memcpy(&server_id_align, server_id, 4);
if (lease) { /*ADDME: or static lease */
sprintf(buffer, "dhcpd.sh dhcprequest %02X:%02X:%02X:%02X:%02X:%02X %d.%d.%d.%d %s",
packet.chaddr[0], packet.chaddr[1], packet.chaddr[2],
packet.chaddr[3], packet.chaddr[4], packet.chaddr[5],
lease->yiaddr & 0xff, (lease->yiaddr >> 8) & 0xff,
(lease->yiaddr >> 16) & 0xff, (lease->yiaddr >> 24) & 0xff,
server_config.ifname[server_config.currentinterface]);
if (server_id) {
/* SELECTING State */
DEBUG(LOG_INFO, "server_id = %08x", ntohl(server_id_align));
if (server_id_align == server_config.server[server_config.currentinterface] && requested &&
requested_align == lease->yiaddr) {
if (WEXITSTATUS(system(buffer)) == 0)
sendACK(&packet, lease->yiaddr);
}
} else {
if (requested) {
/* INIT-REBOOT State */
if (lease->yiaddr == requested_align) {
if (WEXITSTATUS(system(buffer)) == 0)
sendACK(&packet, lease->yiaddr);
}
else sendNAK(&packet);
} else {
/* RENEWING or REBINDING State */
if (lease->yiaddr == packet.ciaddr) {
if (WEXITSTATUS(system(buffer)) == 0)
sendACK(&packet, lease->yiaddr);
}
else {
/* don't know what to do!!!! */
sendNAK(&packet);
}
}
}
/* what to do if we have no record of the client */
} else if (server_id) {
/* SELECTING State */
} else if (requested) {
/* INIT-REBOOT State */
if ((lease = find_lease_by_yiaddr(requested_align))) {
if (lease_expired(lease)) {
/* probably best if we drop this lease */
memset(lease->chaddr, 0, 16);
/* make some contention for this address */
} else sendNAK(&packet);
} else if (requested_align < server_config.start ||
requested_align > server_config.end ||
((requested_align - server_config.start) % server_config.start) == 1) {
sendNAK(&packet);
} /* else remain silent */
} else {
/* RENEWING or REBINDING State */
}
break;
case DHCPDECLINE:
DEBUG(LOG_INFO,"received DECLINE");
if (lease) {
memset(lease->chaddr, 0, 16);
lease->expires = time(0) + server_config.decline_time;
}
break;
case DHCPRELEASE:
DEBUG(LOG_INFO,"received RELEASE");
if (lease) {
sprintf(buffer, "dhcpd.sh release %02X:%02X:%02X:%02X:%02X:%02X %d.%d.%d.%d %s",
packet.chaddr[0], packet.chaddr[1], packet.chaddr[2],
packet.chaddr[3], packet.chaddr[4], packet.chaddr[5],
lease->yiaddr & 0xff, (lease->yiaddr >> 8) & 0xff,
(lease->yiaddr >> 16) & 0xff, (lease->yiaddr >> 24) & 0xff,
server_config.ifname[server_config.currentinterface]);
system(buffer);
lease->expires = time(0);
}
break;
case DHCPINFORM:
DEBUG(LOG_INFO,"received INFORM");
if (lease) {
sprintf(buffer, "dhcpd.sh inform %02X:%02X:%02X:%02X:%02X:%02X %d.%d.%d.%d %s",
packet.chaddr[0], packet.chaddr[1], packet.chaddr[2],
packet.chaddr[3], packet.chaddr[4], packet.chaddr[5],
lease->yiaddr & 0xff, (lease->yiaddr >> 8) & 0xff,
(lease->yiaddr >> 16) & 0xff, (lease->yiaddr >> 24) & 0xff,
server_config.ifname[server_config.currentinterface]);
system(buffer);
send_inform(&packet, lease->yiaddr);
}
break;
default:
LOG(LOG_WARNING, "unsupported DHCP message (%02x) -- ignoring", state[0]);
}
}
return 0;
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: AW: Add new target in mangle table
2008-04-14 16:58 ` Jan Engelhardt
2008-04-15 8:06 ` Manu
2008-04-15 8:10 ` Manu
@ 2008-04-15 8:35 ` manuprivat
2008-04-15 8:46 ` Jan Engelhardt
2 siblings, 1 reply; 12+ messages in thread
From: manuprivat @ 2008-04-15 8:35 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: netfilter-devel
[-- Attachment #1: Type: text/plain, Size: 1067 bytes --]
-------- Original-Nachricht --------
> Datum: Mon, 14 Apr 2008 18:58:41 +0200 (CEST)
> Von: Jan Engelhardt <jengelh@computergmbh.de>
> An: manuprivat@gmx.de
> CC: netfilter-devel@vger.kernel.org
> Betreff: Re: AW: Add new target in mangle table
>
> On Monday 2008-04-14 18:34, manu wrote:
> >> >>
> >> >># iptables -t mangle -I PREROUTING -i eth2 -s 192.168.0.168 -j SADDR
> >> >>--to-source 10.0.19.2
> >> >
> >> One question this throws up... how do you know the address is
> >> 192.168.0.168?
> >
> >Actually, I dont know that! It is only an example to show the different
> >IP-ranges. Excuse my improper representation.
>
> The question is more of a technical one-- if you do not know the
> source address the client will be using, how can you reliably
> mangle the address?
I modified the udhcpd from the busybox - have a look in the attached
file.
To handle the different cases i wrote a shell script - also attached.
--
GMX startet ShortView.de. Hier findest Du Leute mit Deinen Interessen!
Jetzt dabei sein: http://www.shortview.de/?mc=sv_ext_mf@gmx
[-- Attachment #2: dhcpd.c --]
[-- Type: text/x-csrc, Size: 12170 bytes --]
/* dhcpd.c
*
* udhcp Server
* Copyright (C) 1999 Matthew Ramsay <matthewr@moreton.com.au>
* Chris Trew <ctrew@moreton.com.au>
*
* Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <time.h>
#include <sys/time.h>
#include <netpacket/packet.h>
#include "dhcpd.h"
#include "arpping.h"
#include "socket.h"
#include "options.h"
#include "files.h"
#include "serverpacket.h"
#include "common.h"
#include "signalpipe.h"
/* globals */
struct dhcpOfferedAddr *leases;
struct server_config_t server_config;
#ifdef COMBINED_BINARY
int udhcpd_main(int argc, char *argv[])
#else
int main(int argc, char *argv[])
#endif
{
fd_set rfds;
fd_set thefds;
struct timeval tv;
int bytes, retval;
struct dhcpMessage packet;
uint8_t *state;
uint8_t *server_id, *requested;
uint32_t server_id_align, requested_align;
unsigned long timeout_end;
struct option_set *option;
struct dhcpOfferedAddr *lease;
int max_sock = 0;
unsigned long num_ips;
char buffer[100];
char *pname;
int i;
int lastindex = 0;
memset(&server_config, 0, sizeof(struct server_config_t));
read_config(argc < 2 ? DHCPD_CONF_FILE : argv[1]);
/* Start the log, sanitize fd's, and write a pid file */
start_log_and_pid("udhcpd", server_config.pidfile);
if ((option = find_option(server_config.options, DHCP_LEASE_TIME))) {
memcpy(&server_config.lease, option->data + 2, 4);
server_config.lease = ntohl(server_config.lease);
}
else server_config.lease = LEASE_TIME;
/* Sanity check */
server_config.end = ntohl(server_config.start);
server_config.end = htonl(server_config.end + (server_config.max_leases - 1) * server_config.offset);
num_ips = (ntohl(server_config.end) - ntohl(server_config.start)) / server_config.offset + 1;
if (server_config.max_leases > num_ips) {
LOG(LOG_ERR, "max_leases value (%lu) not sane, "
"setting to %lu instead",
server_config.max_leases, num_ips);
server_config.max_leases = num_ips;
}
leases = xcalloc(server_config.max_leases, sizeof(struct dhcpOfferedAddr));
read_leases(server_config.lease_file);
server_config.numofinterfaces = 0;
pname = strtok(server_config.interfaces, " ");
while (pname) {
server_config.ifname[server_config.numofinterfaces] = pname;
server_config.fds[server_config.numofinterfaces] = -1;
server_config.arpfds[server_config.numofinterfaces] = -1;
if (read_interface(server_config.ifname[server_config.numofinterfaces],
&server_config.ifindex[server_config.numofinterfaces],
&server_config.server[server_config.numofinterfaces],
server_config.arp[server_config.numofinterfaces]) < 0)
return 1;
server_config.numofinterfaces++;
pname = strtok(0, " ");
}
server_config.currentinterface = 0;
/* #ifndef UDHCP_DEBUG */
background(server_config.pidfile); /* hold lock during fork. */
/* #endif */
FD_ZERO(&thefds);
FD_ZERO(&rfds);
/* Setup the signal pipe */
udhcp_sp_setup();
timeout_end = time(0) + server_config.auto_time;
while(1) { /* loop until universe collapses */
for (i = 0; i < server_config.numofinterfaces; i++) {
if (server_config.fds[i] < 0)
if ((server_config.fds[i] = listen_socket(INADDR_ANY, SERVER_PORT,
server_config.ifname[i])) < 0) {
LOG(LOG_ERR, "FATAL: couldn't create server socket, %m");
return 2;
}
if (server_config.ippnp) {
if (server_config.arpfds[i] < 0) {
if ((server_config.arpfds[i] =
arp_socket(server_config.ifname[i], server_config.ifindex[i])) < 0) {
LOG(LOG_ERR, "FATAL: couldn't create arp socket, %m");
return 2;
}
}
}
max_sock = udhcp_sp_fd_set(&thefds, server_config.fds[i]);
if (server_config.ippnp) {
max_sock = udhcp_sp_fd_set(&thefds, server_config.arpfds[i]);
}
}
if (server_config.auto_time) {
tv.tv_sec = timeout_end - time(0);
tv.tv_usec = 0;
}
memcpy(&rfds, &thefds, sizeof(fd_set));
if (!server_config.auto_time || tv.tv_sec > 0) {
retval = select(max_sock + 1, &rfds, NULL, NULL,
server_config.auto_time ? &tv : NULL);
} else retval = 0; /* If we already timed out, fall through */
if (retval == 0) {
write_leases();
timeout_end = time(0) + server_config.auto_time;
continue;
} else if (retval < 0 && errno != EINTR) {
DEBUG(LOG_INFO, "error on select");
continue;
}
switch (udhcp_sp_read(&rfds)) {
case SIGUSR1:
LOG(LOG_INFO, "Received a SIGUSR1");
write_leases();
/* why not just reset the timeout, eh */
timeout_end = time(0) + server_config.auto_time;
continue;
case SIGTERM:
LOG(LOG_INFO, "Received a SIGTERM");
write_leases();
return 0;
case 0: break; /* no signal */
default: continue; /* signal or error (probably EINTR) */
}
for (i = lastindex; i < (server_config.numofinterfaces * 2); i++) {
if (FD_ISSET(server_config.fds[i % server_config.numofinterfaces], &rfds)) {
server_config.currentinterface = i % server_config.numofinterfaces;
lastindex = server_config.currentinterface + 1;
break;
}
if (server_config.ippnp) {
if (FD_ISSET(server_config.arpfds[i % server_config.numofinterfaces], &rfds)) {
server_config.currentinterface = i % server_config.numofinterfaces;
lastindex = server_config.currentinterface + 1;
break;
}
}
}
if (server_config.ippnp) {
if (FD_ISSET(server_config.arpfds[server_config.currentinterface], &rfds)) {
unsigned char buf[1024];
struct sockaddr_ll sll;
int sll_len = sizeof(sll);
int n;
n = recvfrom(server_config.arpfds[server_config.currentinterface],
buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr*)&sll, &sll_len);
if (n < 0) {
DEBUG(LOG_INFO, "error receiving arp");
}
else {
DEBUG(LOG_INFO, "received arp on %s %d", server_config.ifname[server_config.currentinterface], n);
handleArpPacket(buf);
}
}
}
if (FD_ISSET(server_config.fds[server_config.currentinterface], &rfds)) {
if ((bytes = get_packet(&packet, server_config.fds[server_config.currentinterface])) < 0) {
if (bytes == -1 && errno != EINTR) {
DEBUG(LOG_INFO, "error on read, %m, reopening socket");
close(server_config.fds[server_config.currentinterface]);
max_sock = udhcp_sp_fd_unset(&thefds, server_config.fds[i]);
server_config.fds[server_config.currentinterface] = -1;
}
continue;
}
}
else
continue;
if ((state = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) {
DEBUG(LOG_ERR, "couldn't get option from packet, ignoring");
continue;
}
/* ADDME: look for a static lease */
lease = find_lease_by_chaddr(packet.chaddr);
if (lease && lease->ippnpaddr) { /* The computer with this mac was seen with fixed ip address before */
char buf[256];
sprintf(buf, "ippnpremove %02X:%02X:%02X:%02X:%02X:%02X %d.%d.%d.%d %s",
lease->chaddr[0], lease->chaddr[1], lease->chaddr[2],
lease->chaddr[3], lease->chaddr[4], lease->chaddr[5],
(lease->yiaddr) & 0xff, (lease->yiaddr >> 8) & 0xff,
(lease->yiaddr >> 16) & 0xff, (lease->yiaddr >> 24) & 0xff,
lease->ifname);
system(buf);
}
switch (state[0]) {
case DHCPDISCOVER:
DEBUG(LOG_INFO,"received DISCOVER");
sprintf(buffer, "dhcpd.sh discover %02X:%02X:%02X:%02X:%02X:%02X %s",
packet.chaddr[0], packet.chaddr[1], packet.chaddr[2],
packet.chaddr[3], packet.chaddr[4], packet.chaddr[5], server_config.ifname[server_config.currentinterface]);
if (WEXITSTATUS(system(buffer)) == 0) {
if (sendOffer(&packet) < 0) {
LOG(LOG_ERR, "send OFFER failed");
}
}
break;
case DHCPREQUEST:
DEBUG(LOG_INFO, "received REQUEST");
requested = get_option(&packet, DHCP_REQUESTED_IP);
server_id = get_option(&packet, DHCP_SERVER_ID);
if (requested) memcpy(&requested_align, requested, 4);
if (server_id) memcpy(&server_id_align, server_id, 4);
if (lease) { /*ADDME: or static lease */
sprintf(buffer, "dhcpd.sh dhcprequest %02X:%02X:%02X:%02X:%02X:%02X %d.%d.%d.%d %s",
packet.chaddr[0], packet.chaddr[1], packet.chaddr[2],
packet.chaddr[3], packet.chaddr[4], packet.chaddr[5],
lease->yiaddr & 0xff, (lease->yiaddr >> 8) & 0xff,
(lease->yiaddr >> 16) & 0xff, (lease->yiaddr >> 24) & 0xff,
server_config.ifname[server_config.currentinterface]);
if (server_id) {
/* SELECTING State */
DEBUG(LOG_INFO, "server_id = %08x", ntohl(server_id_align));
if (server_id_align == server_config.server[server_config.currentinterface] && requested &&
requested_align == lease->yiaddr) {
if (WEXITSTATUS(system(buffer)) == 0)
sendACK(&packet, lease->yiaddr);
}
} else {
if (requested) {
/* INIT-REBOOT State */
if (lease->yiaddr == requested_align) {
if (WEXITSTATUS(system(buffer)) == 0)
sendACK(&packet, lease->yiaddr);
}
else sendNAK(&packet);
} else {
/* RENEWING or REBINDING State */
if (lease->yiaddr == packet.ciaddr) {
if (WEXITSTATUS(system(buffer)) == 0)
sendACK(&packet, lease->yiaddr);
}
else {
/* don't know what to do!!!! */
sendNAK(&packet);
}
}
}
/* what to do if we have no record of the client */
} else if (server_id) {
/* SELECTING State */
} else if (requested) {
/* INIT-REBOOT State */
if ((lease = find_lease_by_yiaddr(requested_align))) {
if (lease_expired(lease)) {
/* probably best if we drop this lease */
memset(lease->chaddr, 0, 16);
/* make some contention for this address */
} else sendNAK(&packet);
} else if (requested_align < server_config.start ||
requested_align > server_config.end ||
((requested_align - server_config.start) % server_config.start) == 1) {
sendNAK(&packet);
} /* else remain silent */
} else {
/* RENEWING or REBINDING State */
}
break;
case DHCPDECLINE:
DEBUG(LOG_INFO,"received DECLINE");
if (lease) {
memset(lease->chaddr, 0, 16);
lease->expires = time(0) + server_config.decline_time;
}
break;
case DHCPRELEASE:
DEBUG(LOG_INFO,"received RELEASE");
if (lease) {
sprintf(buffer, "dhcpd.sh release %02X:%02X:%02X:%02X:%02X:%02X %d.%d.%d.%d %s",
packet.chaddr[0], packet.chaddr[1], packet.chaddr[2],
packet.chaddr[3], packet.chaddr[4], packet.chaddr[5],
lease->yiaddr & 0xff, (lease->yiaddr >> 8) & 0xff,
(lease->yiaddr >> 16) & 0xff, (lease->yiaddr >> 24) & 0xff,
server_config.ifname[server_config.currentinterface]);
system(buffer);
lease->expires = time(0);
}
break;
case DHCPINFORM:
DEBUG(LOG_INFO,"received INFORM");
if (lease) {
sprintf(buffer, "dhcpd.sh inform %02X:%02X:%02X:%02X:%02X:%02X %d.%d.%d.%d %s",
packet.chaddr[0], packet.chaddr[1], packet.chaddr[2],
packet.chaddr[3], packet.chaddr[4], packet.chaddr[5],
lease->yiaddr & 0xff, (lease->yiaddr >> 8) & 0xff,
(lease->yiaddr >> 16) & 0xff, (lease->yiaddr >> 24) & 0xff,
server_config.ifname[server_config.currentinterface]);
system(buffer);
send_inform(&packet, lease->yiaddr);
}
break;
default:
LOG(LOG_WARNING, "unsupported DHCP message (%02x) -- ignoring", state[0]);
}
}
return 0;
}
[-- Attachment #3: dhcpd.sh --]
[-- Type: application/x-shellscript, Size: 8392 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: AW: Add new target in mangle table
2008-04-15 8:35 ` manuprivat
@ 2008-04-15 8:46 ` Jan Engelhardt
2008-04-15 9:20 ` manuel scheub
0 siblings, 1 reply; 12+ messages in thread
From: Jan Engelhardt @ 2008-04-15 8:46 UTC (permalink / raw)
To: manuprivat; +Cc: netfilter-devel
On Tuesday 2008-04-15 10:35, manuprivat@gmx.de wrote:
>> >> >># iptables -t mangle -I PREROUTING -i eth2 -s 192.168.0.168 -j SADDR
>> >> >>--to-source 10.0.19.2
>> >> >
>> >> One question this throws up... how do you know the address is
>> >> 192.168.0.168?
>> >
>> >Actually, I dont know that! It is only an example to show the different
>> >IP-ranges. Excuse my improper representation.
>>
>> The question is more of a technical one-- if you do not know the
>> source address the client will be using, how can you reliably
>> mangle the address?
>
>I modified the udhcpd from the busybox - have a look in the attached
>file.
>To handle the different cases i wrote a shell script - also attached.
But if the client uses DHCP, why don't you hand out 10.0.x.x directly?
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: AW: Add new target in mangle table
2008-04-15 8:46 ` Jan Engelhardt
@ 2008-04-15 9:20 ` manuel scheub
2008-04-15 9:52 ` Jan Engelhardt
0 siblings, 1 reply; 12+ messages in thread
From: manuel scheub @ 2008-04-15 9:20 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: netfilter-devel
-------- Original-Nachricht --------
> Datum: Tue, 15 Apr 2008 10:46:35 +0200 (CEST)
> Von: Jan Engelhardt <jengelh@computergmbh.de>
> An: manuprivat@gmx.de
> CC: netfilter-devel@vger.kernel.org
> Betreff: Re: AW: Add new target in mangle table
>
> On Tuesday 2008-04-15 10:35, manuprivat@gmx.de wrote:
> >> >> >># iptables -t mangle -I PREROUTING -i eth2 -s 192.168.0.168 -j
> SADDR
> >> >> >>--to-source 10.0.19.2
> >> >> >
> >> >> One question this throws up... how do you know the address is
> >> >> 192.168.0.168?
> >> >
> >> >Actually, I dont know that! It is only an example to show the
> different
> >> >IP-ranges. Excuse my improper representation.
> >>
> >> The question is more of a technical one-- if you do not know the
> >> source address the client will be using, how can you reliably
> >> mangle the address?
> >
> >I modified the udhcpd from the busybox - have a look in the attached
> >file.
> >To handle the different cases i wrote a shell script - also attached.
>
> But if the client uses DHCP, why don't you hand out 10.0.x.x directly?
If the client uses DHCP, i do hand out 10.0.x.x directly! The modified dhcpd listens on all requests, it doesn't matter if it is not a dhcp-request. And for the internal use of the gateway it provides a dhcp-lease, even if the request came from a user with a fix-ip entry.
--
Psst! Geheimtipp: Online Games kostenlos spielen bei den GMX Free Games!
http://games.entertainment.gmx.net/de/entertainment/games/free
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: AW: Add new target in mangle table
2008-04-15 9:20 ` manuel scheub
@ 2008-04-15 9:52 ` Jan Engelhardt
2008-04-15 12:47 ` manuel scheub
0 siblings, 1 reply; 12+ messages in thread
From: Jan Engelhardt @ 2008-04-15 9:52 UTC (permalink / raw)
To: manuel scheub; +Cc: netfilter-devel
On Tuesday 2008-04-15 11:20, manuel scheub wrote:
>> >
>> >I modified the udhcpd from the busybox - have a look in the attached
>> >file.
>> >To handle the different cases i wrote a shell script - also attached.
>>
>> But if the client uses DHCP, why don't you hand out 10.0.x.x directly?
>
>If the client uses DHCP, i do hand out 10.0.x.x directly! The
>modified dhcpd listens on all requests, it doesn't matter if it is
>not a dhcp-request.
But there is only DHCPINFORM which might carry a non 10.0.x.x
address.
I think it's simpler if you just add 192.168.0.0/16 as an
address to eth0.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: AW: Add new target in mangle table
2008-04-15 9:52 ` Jan Engelhardt
@ 2008-04-15 12:47 ` manuel scheub
0 siblings, 0 replies; 12+ messages in thread
From: manuel scheub @ 2008-04-15 12:47 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: netfilter-devel
[-- Attachment #1: Type: text/plain, Size: 1511 bytes --]
-------- Original-Nachricht --------
> Datum: Tue, 15 Apr 2008 11:52:06 +0200 (CEST)
> Von: Jan Engelhardt <jengelh@computergmbh.de>
> An: manuel scheub <manuprivat@gmx.de>
> CC: netfilter-devel@vger.kernel.org
> Betreff: Re: AW: Add new target in mangle table
>
> On Tuesday 2008-04-15 11:20, manuel scheub wrote:
> >> >
> >> >I modified the udhcpd from the busybox - have a look in the attached
> >> >file.
> >> >To handle the different cases i wrote a shell script - also attached.
> >>
> >> But if the client uses DHCP, why don't you hand out 10.0.x.x directly?
> >
> >If the client uses DHCP, i do hand out 10.0.x.x directly! The
> >modified dhcpd listens on all requests, it doesn't matter if it is
> >not a dhcp-request.
>
> But there is only DHCPINFORM which might carry a non 10.0.x.x
> address.
> I think it's simpler if you just add 192.168.0.0/16 as an
> address to eth0.
There are some more modifications in the source code for the udhcp stuff in busybox. I think I didn't give you the correct information about the ip-plug'n'play with the dhcpd.c file. I've attached some more files, the main point is in the arpping.c. I've also attatched the file ippnpadd with the filter rules (there is also a file ippnpremove).
If I add 192.168.0.0/16, I didn't get the users with fix ip entries 10.120.0.1, 172.123.1.0,... maybe some business guys have these ip's.
--
Der GMX SmartSurfer hilft bis zu 70% Ihrer Onlinekosten zu sparen!
Ideal für Modem und ISDN: http://www.gmx.net/de/go/smartsurfer
[-- Attachment #2: arpping.c --]
[-- Type: text/x-csrc, Size: 7263 bytes --]
/*
* arpping.c
*
* Mostly stolen from: dhcpcd - DHCP client daemon
* by Yoichi Hariguchi <yoichi@fore.com>
*/
#include <sys/time.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/if_ether.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "dhcpd.h"
#include "arpping.h"
#include "common.h"
#include "options.h"
/* args: yiaddr - what IP to ping
* ip - our ip
* mac - our arp address
* interface - interface to use
* retn: 1 addr free
* 0 addr used
* -1 error
*/
/* FIXME: match response against chaddr */
int arpping(uint32_t yiaddr, uint32_t ip, uint8_t *mac, char *interface)
{
int timeout = 2;
int optval = 1;
int s; /* socket */
int rv = 1; /* return value */
struct sockaddr addr; /* for interface name */
struct arpMsg arp;
fd_set fdset;
struct timeval tm;
time_t prevTime;
if ((s = socket (PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP))) == -1) {
#ifdef IN_BUSYBOX
LOG(LOG_ERR, bb_msg_can_not_create_raw_socket);
#else
LOG(LOG_ERR, "Could not open raw socket");
#endif
return -1;
}
if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) == -1) {
LOG(LOG_ERR, "Could not setsocketopt on raw socket");
close(s);
return -1;
}
/* send arp request */
memset(&arp, 0, sizeof(arp));
memcpy(arp.ethhdr.h_dest, MAC_BCAST_ADDR, 6); /* MAC DA */
memcpy(arp.ethhdr.h_source, mac, 6); /* MAC SA */
arp.ethhdr.h_proto = htons(ETH_P_ARP); /* protocol type (Ethernet) */
arp.htype = htons(ARPHRD_ETHER); /* hardware type */
arp.ptype = htons(ETH_P_IP); /* protocol type (ARP message) */
arp.hlen = 6; /* hardware address length */
arp.plen = 4; /* protocol address length */
arp.operation = htons(ARPOP_REQUEST); /* ARP op code */
memcpy(arp.sInaddr, &ip, sizeof(ip)); /* source IP address */
memcpy(arp.sHaddr, mac, 6); /* source hardware address */
memcpy(arp.tInaddr, &yiaddr, sizeof(yiaddr)); /* target IP address */
memset(&addr, 0, sizeof(addr));
strcpy(addr.sa_data, interface);
if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0)
rv = 0;
/* wait arp reply, and check it */
tm.tv_usec = 0;
time(&prevTime);
while (timeout > 0) {
FD_ZERO(&fdset);
FD_SET(s, &fdset);
tm.tv_sec = timeout;
if (select(s + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL, &tm) < 0) {
DEBUG(LOG_ERR, "Error on ARPING request: %m");
if (errno != EINTR) rv = 0;
} else if (FD_ISSET(s, &fdset)) {
if (recv(s, &arp, sizeof(arp), 0) < 0 ) rv = 0;
if (arp.operation == htons(ARPOP_REPLY) &&
bcmp(arp.tHaddr, mac, 6) == 0 &&
*((uint32_t *) arp.sInaddr) == yiaddr) {
DEBUG(LOG_INFO, "Valid arp reply receved for this address");
rv = 0;
break;
}
}
timeout -= time(NULL) - prevTime;
time(&prevTime);
}
close(s);
DEBUG(LOG_INFO, "%salid arp replies for this address", rv ? "No v" : "V");
return rv;
}
struct arpPacket {
uint16_t htype; /* hardware type (must be ARPHRD_ETHER) */
uint16_t ptype; /* protocol type (must be ETH_P_IP) */
uint8_t hlen; /* hardware address length (must be 6) */
uint8_t plen; /* protocol address length (must be 4) */
uint16_t operation; /* ARP opcode */
uint8_t sHaddr[6]; /* sender's hardware address */
uint8_t sInaddr[4]; /* sender's IP address */
uint8_t tHaddr[6]; /* target's hardware address */
uint8_t tInaddr[4]; /* target's IP address */
uint8_t pad[18]; /* pad for min. Ethernet payload (60 bytes) */
};
void handleArpRequest(unsigned char *mac, uint32_t ip)
{
uint32_t freeaddr = 0;
struct dhcpOfferedAddr *lease = find_lease_by_chaddr(mac);
if (lease) {
char buf[256];
if (lease->ippnpaddr == ip) {
if (!lease_expired(lease)) {
lease->expires = time(0) + server_config.lease;
DEBUG(LOG_INFO, "handleArpRequest: ip-addresses match");
return;
}
DEBUG(LOG_INFO, "handleArpRequest: ip-addresses match but expired");
}
else if (!lease_expired(lease)) {
if (ip == lease->yiaddr) {
DEBUG(LOG_INFO, "handleArpRequest: assume dhcp lease");
return;
}
}
DEBUG(LOG_INFO, "handleArpRequest: ip-addresses differ %08X %08X", lease->ippnpaddr, ip);
sprintf(buf, "ippnpremove %02X:%02X:%02X:%02X:%02X:%02X %d.%d.%d.%d %s",
lease->chaddr[0], lease->chaddr[1], lease->chaddr[2],
lease->chaddr[3], lease->chaddr[4], lease->chaddr[5],
(lease->yiaddr) & 0xff, (lease->yiaddr >> 8) & 0xff,
(lease->yiaddr >> 16) & 0xff, (lease->yiaddr >> 24) & 0xff,
lease->ifname);
DEBUG(LOG_INFO, "Exec %s", buf);
system(buf);
freeaddr = lease->yiaddr;
clear_lease(lease->chaddr, lease->yiaddr);
}
else
freeaddr = find_address(0);
if (!freeaddr)
freeaddr = find_address(1);
if (freeaddr) {
struct option_set *o = find_option(server_config.options, DHCP_ROUTER);
add_lease(mac, freeaddr, server_config.offer_time, ip, server_config.ifname[server_config.currentinterface]);
if (o) {
uint32_t gaddr;
uint32_t extip1 = ip;
unsigned char *pgaddr = (char *) &gaddr;
unsigned char *pintip = (char *) &freeaddr;
unsigned char *pextip = (char *) &ip;
unsigned char *pextip1 = (char *) &extip1;
char command[256];
memcpy(&gaddr, &o->data[2], 4);
if (server_config.offset != 1) {
int leasenumber = (ntohl(freeaddr) - ntohl(server_config.start)) / server_config.offset;
gaddr = ntohl(gaddr);
gaddr += (server_config.offset * leasenumber);
gaddr = htonl(gaddr);
}
if (pextip1[3] == 1)
pextip1[3]++;
else
pextip1[3]--;
sprintf(command, "ippnpadd %02X:%02X:%02X:%02X:%02X:%02X %d.%d.%d.%d %d.%d.%d.%d %d.%d.%d.%d %d.%d.%d.%d %s",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
pgaddr[0], pgaddr[1], pgaddr[2], pgaddr[3],
pintip[0], pintip[1], pintip[2], pintip[3],
pextip[0], pextip[1], pextip[2], pextip[3],
pextip1[0], pextip1[1], pextip1[2], pextip1[3],
server_config.ifname[server_config.currentinterface]);
DEBUG(LOG_INFO, "Exec %s", command);
system(command);
}
}
}
int handleArpPacket(uint8_t *a)
{
struct arpPacket *arp = (struct arpPacket *) a;
DEBUG(LOG_INFO, "%d %d %d %d %d\n", arp->htype, arp->ptype, arp->hlen, arp->plen, ntohs(arp->operation));
DEBUG(LOG_INFO, "%02x:%02x:%02x:%02x:%02x:%02x %d.%d.%d.%d %02x:%02x:%02x:%02x:%02x:%02x %d.%d.%d.%d\n",
arp->sHaddr[0], arp->sHaddr[1], arp->sHaddr[2], arp->sHaddr[3], arp->sHaddr[4], arp->sHaddr[5],
arp->sInaddr[0], arp->sInaddr[1], arp->sInaddr[2], arp->sInaddr[3],
arp->tHaddr[0], arp->tHaddr[1], arp->tHaddr[2], arp->tHaddr[3], arp->tHaddr[4], arp->tHaddr[5],
arp->tInaddr[0], arp->tInaddr[1], arp->tInaddr[2], arp->tInaddr[3]
);
if (ntohs(arp->operation) == 1 && memcmp(server_config.arp[server_config.currentinterface], arp->sHaddr, 6) != 0) {
uint32_t ip;
unsigned char chaddr[16];
memset(chaddr, 0, 16);
memcpy(chaddr, arp->sHaddr, 6);
memcpy(&ip, arp->sInaddr, 4);
handleArpRequest(chaddr, ip);
}
return 0;
}
[-- Attachment #3: files.c --]
[-- Type: text/x-csrc, Size: 9227 bytes --]
/*
* files.c -- DHCP server file manipulation *
* Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001
*/
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <netdb.h>
#include "dhcpd.h"
#include "files.h"
#include "options.h"
#include "common.h"
/*
* Domain names may have 254 chars, and string options can be 254
* chars long. However, 80 bytes will be enough for most, and won't
* hog up memory. If you have a special application, change it
*/
#define READ_CONFIG_BUF_SIZE 16384
/* on these functions, make sure you datatype matches */
static int read_ip(const char *line, void *arg)
{
struct in_addr *addr = arg;
struct hostent *host;
int retval = 1;
if (!inet_aton(line, addr)) {
if ((host = gethostbyname(line)))
addr->s_addr = *((unsigned long *) host->h_addr_list[0]);
else retval = 0;
}
return retval;
}
static int read_str(const char *line, void *arg)
{
char **dest = arg;
if (*dest) free(*dest);
*dest = strdup(line);
return 1;
}
static int read_u32(const char *line, void *arg)
{
uint32_t *dest = arg;
char *endptr;
*dest = strtoul(line, &endptr, 0);
return endptr[0] == '\0';
}
static int read_yn(const char *line, void *arg)
{
char *dest = arg;
int retval = 1;
if (!strcasecmp("yes", line))
*dest = 1;
else if (!strcasecmp("no", line))
*dest = 0;
else retval = 0;
return retval;
}
/* read a dhcp option and add it to opt_list */
static int read_opt(const char *const_line, void *arg)
{
struct option_set **opt_list = arg;
char *opt, *val, *endptr;
struct dhcp_option *option;
int retval = 0, length;
char buffer[8];
char *line;
uint16_t *result_u16 = (uint16_t *) buffer;
uint32_t *result_u32 = (uint32_t *) buffer;
/* Cheat, the only const line we'll actually get is "" */
line = (char *) const_line;
if (!(opt = strtok(line, " \t="))) return 0;
for (option = dhcp_options; option->code; option++)
if (!strcasecmp(option->name, opt))
break;
if (!option->code) return 0;
do {
if (!(val = strtok(NULL, ", \t"))) break;
length = option_lengths[option->flags & TYPE_MASK];
retval = 0;
opt = buffer; /* new meaning for variable opt */
switch (option->flags & TYPE_MASK) {
case OPTION_IP:
retval = read_ip(val, buffer);
break;
case OPTION_IP_PAIR:
retval = read_ip(val, buffer);
if (!(val = strtok(NULL, ", \t/-"))) retval = 0;
if (retval) retval = read_ip(val, buffer + 4);
break;
case OPTION_STRING:
length = strlen(val);
if (length > 0) {
if (length > 254) length = 254;
opt = val;
retval = 1;
}
break;
case OPTION_BOOLEAN:
retval = read_yn(val, buffer);
break;
case OPTION_U8:
buffer[0] = strtoul(val, &endptr, 0);
retval = (endptr[0] == '\0');
break;
case OPTION_U16:
*result_u16 = htons(strtoul(val, &endptr, 0));
retval = (endptr[0] == '\0');
break;
case OPTION_S16:
*result_u16 = htons(strtol(val, &endptr, 0));
retval = (endptr[0] == '\0');
break;
case OPTION_U32:
*result_u32 = htonl(strtoul(val, &endptr, 0));
retval = (endptr[0] == '\0');
break;
case OPTION_S32:
*result_u32 = htonl(strtol(val, &endptr, 0));
retval = (endptr[0] == '\0');
break;
default:
break;
}
if (retval)
attach_option(opt_list, option, opt, length);
} while (retval && option->flags & OPTION_LIST);
return retval;
}
static const struct config_keyword keywords[] = {
/* keyword handler variable address default */
{"start", read_ip, &(server_config.start), "192.168.0.20"},
{"end", read_ip, &(server_config.end), "192.168.0.254"},
{"interface", read_str, &(server_config.interfaces), "eth0"},
{"option", read_opt, &(server_config.options), ""},
{"opt", read_opt, &(server_config.options), ""},
{"max_leases", read_u32, &(server_config.max_leases), "254"},
{"offset", read_u32, &(server_config.offset), "1"},
{"send_mult", read_u32, &(server_config.send_mult), "1"},
{"keep_dns", read_u32, &(server_config.keep_dns), "0"},
{"ippnp", read_u32, &(server_config.ippnp), "0"},
{"remaining", read_yn, &(server_config.remaining), "yes"},
{"auto_time", read_u32, &(server_config.auto_time), "7200"},
{"decline_time",read_u32, &(server_config.decline_time),"3600"},
{"conflict_time",read_u32,&(server_config.conflict_time),"3600"},
{"offer_time", read_u32, &(server_config.offer_time), "60"},
{"min_lease", read_u32, &(server_config.min_lease), "60"},
{"lease_file", read_str, &(server_config.lease_file), LEASES_FILE},
{"pidfile", read_str, &(server_config.pidfile), "/var/run/udhcpd.pid"},
{"notify_file", read_str, &(server_config.notify_file), ""},
{"siaddr", read_ip, &(server_config.siaddr), "0.0.0.0"},
{"sname", read_str, &(server_config.sname), ""},
{"boot_file", read_str, &(server_config.boot_file), ""},
/*ADDME: static lease */
{"", NULL, NULL, ""}
};
int read_config(const char *file)
{
FILE *in;
char buffer[READ_CONFIG_BUF_SIZE], *token, *line;
#ifdef UDHCP_DEBUG
char orig[READ_CONFIG_BUF_SIZE];
#endif
int i, lm = 0;
for (i = 0; keywords[i].keyword[0]; i++)
if (keywords[i].def[0])
keywords[i].handler(keywords[i].def, keywords[i].var);
if (!(in = fopen(file, "r"))) {
LOG(LOG_ERR, "unable to open config file: %s", file);
return 0;
}
while (fgets(buffer, READ_CONFIG_BUF_SIZE, in)) {
lm++;
if (strchr(buffer, '\n')) *(strchr(buffer, '\n')) = '\0';
#ifdef UDHCP_DEBUG
strcpy(orig, buffer);
#endif
if (strchr(buffer, '#')) *(strchr(buffer, '#')) = '\0';
if (!(token = strtok(buffer, " \t"))) continue;
if (!(line = strtok(NULL, ""))) continue;
/* eat leading whitespace */
line = line + strspn(line, " \t=");
/* eat trailing whitespace */
for (i = strlen(line); i > 0 && isspace(line[i - 1]); i--);
line[i] = '\0';
for (i = 0; keywords[i].keyword[0]; i++)
if (!strcasecmp(token, keywords[i].keyword))
if (!keywords[i].handler(line, keywords[i].var)) {
LOG(LOG_ERR, "Failure parsing line %d of %s", lm, file);
DEBUG(LOG_ERR, "unable to parse '%s'", orig);
/* reset back to the default value */
keywords[i].handler(keywords[i].def, keywords[i].var);
}
}
fclose(in);
return 1;
}
void write_leases(void)
{
FILE *fp;
unsigned int i;
char buf[255];
time_t curr = time(0);
unsigned long tmp_time;
if (!(fp = fopen(server_config.lease_file, "w"))) {
LOG(LOG_ERR, "Unable to open %s for writing", server_config.lease_file);
return;
}
for (i = 0; i < server_config.max_leases; i++) {
if (leases[i].yiaddr != 0) {
/* screw with the time in the struct, for easier writing */
tmp_time = leases[i].expires;
if (server_config.remaining) {
if (lease_expired(&(leases[i]))) {
if (leases[i].expires + server_config.auto_time + 20 >= curr) {
if (leases[i].ippnpaddr) {
sprintf(buf, "ippnpremove %02X:%02X:%02X:%02X:%02X:%02X %d.%d.%d.%d %s",
leases[i].chaddr[0], leases[i].chaddr[1], leases[i].chaddr[2],
leases[i].chaddr[3], leases[i].chaddr[4], leases[i].chaddr[5],
leases[i].yiaddr & 0xff, (leases[i].yiaddr >> 8) & 0xff,
(leases[i].yiaddr >> 16) & 0xff, (leases[i].yiaddr >> 24) & 0xff,
leases[i].ifname);
DEBUG(LOG_INFO, "Exec %s", buf);
system(buf);
} else {
sprintf(buf, "dhcpd.sh release %02X:%02X:%02X:%02X:%02X:%02X %d.%d.%d.%d %s",
leases[i].chaddr[0], leases[i].chaddr[1], leases[i].chaddr[2],
leases[i].chaddr[3], leases[i].chaddr[4], leases[i].chaddr[5],
leases[i].yiaddr & 0xff, (leases[i].yiaddr >> 8) & 0xff,
(leases[i].yiaddr >> 16) & 0xff, (leases[i].yiaddr >> 24) & 0xff,
leases[i].ifname );
DEBUG(LOG_INFO, "Exec %s", buf);
system(buf);
}
}
leases[i].expires = 0;
}
else leases[i].expires -= curr;
} /* else stick with the time we got */
leases[i].expires = htonl(leases[i].expires);
fwrite(&leases[i], sizeof(struct dhcpOfferedAddr), 1, fp);
/* Then restore it when done. */
leases[i].expires = tmp_time;
}
}
fclose(fp);
if (server_config.notify_file) {
sprintf(buf, "%s %s", server_config.notify_file, server_config.lease_file);
system(buf);
}
}
void read_leases(const char *file)
{
FILE *fp;
unsigned int i = 0;
struct dhcpOfferedAddr lease;
struct stat buf;
if (!(fp = fopen(file, "r"))) {
LOG(LOG_ERR, "Unable to open %s for reading", file);
return;
}
if (fstat(fileno(fp), &buf) != 0) {
LOG(LOG_ERR, "Unable to get filesize for %s", file);
return;
}
if (buf.st_size % (sizeof lease) != 0) {
LOG(LOG_ERR, "Probably unknown file structure in %s", file);
return;
}
while (i < server_config.max_leases && (fread(&lease, sizeof lease, 1, fp) == 1)) {
/* ADDME: is it a static lease */
if (lease.yiaddr >= server_config.start && lease.yiaddr <= server_config.end) {
lease.expires = ntohl(lease.expires);
if (!server_config.remaining) lease.expires -= time(0);
if (!(add_lease(lease.chaddr, lease.yiaddr, lease.expires, lease.ippnpaddr, lease.ifname))) {
LOG(LOG_WARNING, "Too many leases while loading %s\n", file);
break;
}
i++;
}
}
DEBUG(LOG_INFO, "Read %d leases", i);
fclose(fp);
}
[-- Attachment #4: leases.c --]
[-- Type: text/x-csrc, Size: 4899 bytes --]
/*
* leases.c -- tools to manage DHCP leases
* Russ Dill <Russ.Dill@asu.edu> July 2001
*/
#include <time.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "dhcpd.h"
#include "files.h"
#include "options.h"
#include "leases.h"
#include "arpping.h"
#include "common.h"
uint8_t blank_chaddr[] = {[0 ... 15] = 0};
/* clear every lease out that chaddr OR yiaddr matches and is nonzero */
void clear_lease(uint8_t *chaddr, uint32_t yiaddr)
{
unsigned int i, j;
for (j = 0; j < 16 && !chaddr[j]; j++);
for (i = 0; i < server_config.max_leases; i++)
if ((j != 16 && !memcmp(leases[i].chaddr, chaddr, 16)) ||
(yiaddr && leases[i].yiaddr == yiaddr)) {
memset(&(leases[i]), 0, sizeof(struct dhcpOfferedAddr));
}
}
/* add a lease into the table, clearing out any old ones */
struct dhcpOfferedAddr *add_lease(uint8_t *chaddr, uint32_t yiaddr, unsigned long lease, uint32_t ippnpaddr, char *ifname)
{
struct dhcpOfferedAddr *oldest;
/* clean out any old ones */
clear_lease(chaddr, yiaddr);
oldest = oldest_expired_lease();
if (oldest) {
memcpy(oldest->chaddr, chaddr, 16);
oldest->yiaddr = yiaddr;
oldest->expires = time(0) + lease;
oldest->ippnpaddr = ippnpaddr;
strcpy(oldest->ifname, ifname);
}
return oldest;
}
/* true if a lease has expired */
int lease_expired(struct dhcpOfferedAddr *lease)
{
return (lease->expires < (unsigned long) time(0));
}
/* Find the oldest expired lease, NULL if there are no expired leases */
struct dhcpOfferedAddr *oldest_expired_lease(void)
{
struct dhcpOfferedAddr *oldest = NULL;
unsigned long oldest_lease = time(0);
unsigned int i;
for (i = 0; i < server_config.max_leases; i++)
if (oldest_lease > leases[i].expires) {
oldest_lease = leases[i].expires;
oldest = &(leases[i]);
}
return oldest;
}
/* Find the first lease that matches chaddr, NULL if no match */
struct dhcpOfferedAddr *find_lease_by_chaddr(uint8_t *chaddr)
{
unsigned int i;
for (i = 0; i < server_config.max_leases; i++)
if (!memcmp(leases[i].chaddr, chaddr, 16)) return &(leases[i]);
return NULL;
}
/* Find the first lease that matches yiaddr, NULL is no match */
struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr)
{
unsigned int i;
for (i = 0; i < server_config.max_leases; i++)
if (leases[i].yiaddr == yiaddr) return &(leases[i]);
return NULL;
}
/* check is an IP is taken, if it is, add it to the lease table */
static int check_ip(uint32_t addr)
{
struct in_addr temp;
if (arpping(addr, server_config.server[server_config.currentinterface],
server_config.arp[server_config.currentinterface], server_config.ifname[server_config.currentinterface]) == 0) {
temp.s_addr = addr;
LOG(LOG_INFO, "%s belongs to someone, reserving it for %ld seconds",
inet_ntoa(temp), server_config.conflict_time);
add_lease(blank_chaddr, addr, server_config.conflict_time, 0, "");
return 1;
} else return 0;
}
/* find an assignable address, it check_expired is true, we check all the expired leases as well.
* Maybe this should try expired leases by age... */
uint32_t find_address(int check_expired)
{
uint32_t addr;
uint32_t ret = 0;
struct dhcpOfferedAddr *lease = NULL;
addr = ntohl(server_config.start); /* addr is in host order here */
for (;addr <= ntohl(server_config.end); addr += server_config.offset) {
/* ie, 192.168.55.0 */
if (!(addr & 0xFF)) continue;
/* ie, 192.168.55.255 */
if ((addr & 0xFF) == 0xFF) continue;
/* lease is not taken */
ret = htonl(addr);
if ((!(find_lease_by_yiaddr(ret))) &&
/* and it isn't on the network */
!check_ip(ret)) {
return ret;
}
}
if (!check_expired)
return 0;
while ((lease = oldest_expired_lease()) != 0) {
/* ie, 192.168.55.0 */
/* if (!(addr & 0xFF)) continue */;
/* ie, 192.168.55.255 */
/* if ((addr & 0xFF) == 0xFF) continue */
/* and it isn't on the network */
if (!check_ip(lease->yiaddr)) {
if (lease->expires + server_config.auto_time + 20 >= time(0)) {
char buf[255];
sprintf(buf, "dhcpd.sh release %02X:%02X:%02X:%02X:%02X:%02X %d.%d.%d.%d %s",
lease->chaddr[0], lease->chaddr[1], lease->chaddr[2],
lease->chaddr[3], lease->chaddr[4], lease->chaddr[5],
lease->yiaddr & 0xff, (lease->yiaddr >> 8) & 0xff,
(lease->yiaddr >> 16) & 0xff, (lease->yiaddr >> 24) & 0xff,
lease->ifname);
system(buf);
if (lease->ippnpaddr) {
sprintf(buf, "ippnpremove %02X:%02X:%02X:%02X:%02X:%02X %d.%d.%d.%d %s",
lease->chaddr[0], lease->chaddr[1], lease->chaddr[2],
lease->chaddr[3], lease->chaddr[4], lease->chaddr[5],
(lease->yiaddr) & 0xff, (lease->yiaddr >> 8) & 0xff,
(lease->yiaddr >> 16) & 0xff, (lease->yiaddr >> 24) & 0xff,
lease->ifname);
DEBUG(LOG_INFO, "Exec %s", buf);
system(buf);
}
}
return lease->yiaddr;
}
}
return 0;
}
[-- Attachment #5: options.c --]
[-- Type: text/x-csrc, Size: 6850 bytes --]
/*
* options.c -- DHCP server option packet tools
* Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001
*/
#include <stdlib.h>
#include <string.h>
#include "dhcpd.h"
#include "files.h"
#include "options.h"
#include "common.h"
/* supported options are easily added here */
struct dhcp_option dhcp_options[] = {
/* name[10] flags code */
{"subnet", OPTION_IP | OPTION_REQ, 0x01},
{"timezone", OPTION_S32, 0x02},
{"router", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x03},
{"timesvr", OPTION_IP | OPTION_LIST, 0x04},
{"namesvr", OPTION_IP | OPTION_LIST, 0x05},
{"dns", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x06},
{"logsvr", OPTION_IP | OPTION_LIST, 0x07},
{"cookiesvr", OPTION_IP | OPTION_LIST, 0x08},
{"lprsvr", OPTION_IP | OPTION_LIST, 0x09},
{"hostname", OPTION_STRING | OPTION_REQ, 0x0c},
{"bootsize", OPTION_U16, 0x0d},
{"domain", OPTION_STRING | OPTION_REQ, 0x0f},
{"swapsvr", OPTION_IP, 0x10},
{"rootpath", OPTION_STRING, 0x11},
{"ipttl", OPTION_U8, 0x17},
{"mtu", OPTION_U16, 0x1a},
{"broadcast", OPTION_IP | OPTION_REQ, 0x1c},
{"ntpsrv", OPTION_IP | OPTION_LIST, 0x2a},
{"wins", OPTION_IP | OPTION_LIST, 0x2c},
{"requestip", OPTION_IP, 0x32},
{"lease", OPTION_U32, 0x33},
{"dhcptype", OPTION_U8, 0x35},
{"serverid", OPTION_IP, 0x36},
{"message", OPTION_STRING, 0x38},
{"tftp", OPTION_STRING, 0x42},
{"bootfile", OPTION_STRING, 0x43},
{"", 0x00, 0x00}
};
/* Lengths of the different option types */
int option_lengths[] = {
[OPTION_IP] = 4,
[OPTION_IP_PAIR] = 8,
[OPTION_BOOLEAN] = 1,
[OPTION_STRING] = 1,
[OPTION_U8] = 1,
[OPTION_U16] = 2,
[OPTION_S16] = 2,
[OPTION_U32] = 4,
[OPTION_S32] = 4
};
/* get an option with bounds checking (warning, not aligned). */
uint8_t *get_option(struct dhcpMessage *packet, int code)
{
int i, length;
uint8_t *optionptr;
int over = 0, done = 0, curr = OPTION_FIELD;
optionptr = packet->options;
i = 0;
length = 308;
while (!done) {
if (i >= length) {
LOG(LOG_WARNING, "bogus packet, option fields too long.");
return NULL;
}
if (optionptr[i + OPT_CODE] == code) {
if (i + 1 + optionptr[i + OPT_LEN] >= length) {
LOG(LOG_WARNING, "bogus packet, option fields too long.");
return NULL;
}
return optionptr + i + 2;
}
switch (optionptr[i + OPT_CODE]) {
case DHCP_PADDING:
i++;
break;
case DHCP_OPTION_OVER:
if (i + 1 + optionptr[i + OPT_LEN] >= length) {
LOG(LOG_WARNING, "bogus packet, option fields too long.");
return NULL;
}
over = optionptr[i + 3];
i += optionptr[OPT_LEN] + 2;
break;
case DHCP_END:
if (curr == OPTION_FIELD && over & FILE_FIELD) {
optionptr = packet->file;
i = 0;
length = 128;
curr = FILE_FIELD;
} else if (curr == FILE_FIELD && over & SNAME_FIELD) {
optionptr = packet->sname;
i = 0;
length = 64;
curr = SNAME_FIELD;
} else done = 1;
break;
default:
i += optionptr[OPT_LEN + i] + 2;
}
}
return NULL;
}
/* return the position of the 'end' option (no bounds checking) */
int end_option(uint8_t *optionptr)
{
int i = 0;
while (optionptr[i] != DHCP_END) {
if (optionptr[i] == DHCP_PADDING) i++;
else i += optionptr[i + OPT_LEN] + 2;
}
return i;
}
/* add an option string to the options (an option string contains an option code,
* length, then data) */
int add_option_string(uint8_t *optionptr, uint8_t *string, uint32_t leasenumber)
{
int end = end_option(optionptr);
uint8_t buffer[255];
/* end position + string length + option code/length + end option */
if (end + string[OPT_LEN] + 2 + 1 >= 308) {
LOG(LOG_ERR, "Option 0x%02x did not fit into the packet!", string[OPT_CODE]);
return 0;
}
DEBUG(LOG_INFO, "adding option 0x%02x", string[OPT_CODE]);
memcpy(buffer, string, string[OPT_LEN] + 2);
if (buffer[OPT_CODE] == 0x03) {
if (server_config.offset != 1) {
uint32_t addr;
memcpy(&addr, &buffer[2], 4);
addr = ntohl(addr);
addr += (server_config.offset * leasenumber);
addr = htonl(addr);
memcpy(&buffer[2], &addr, 4);
}
}
if (buffer[OPT_CODE] == 0x05 || buffer[OPT_CODE] == 0x06) {
if (server_config.offset != 1 && !server_config.keep_dns) {
uint32_t addr;
memcpy(&addr, &buffer[2], 4);
addr = ntohl(addr);
addr += (server_config.offset * leasenumber);
addr = htonl(addr);
memcpy(&buffer[2], &addr, 4);
}
}
memcpy(optionptr + end, buffer, buffer[OPT_LEN] + 2);
optionptr[end + string[OPT_LEN] + 2] = DHCP_END;
return string[OPT_LEN] + 2;
}
/* add a one to four byte option to a packet */
int add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data)
{
char length = 0;
int i;
uint8_t option[2 + 4];
uint8_t *u8;
uint16_t *u16;
uint32_t *u32;
uint32_t aligned;
u8 = (uint8_t *) &aligned;
u16 = (uint16_t *) &aligned;
u32 = &aligned;
for (i = 0; dhcp_options[i].code; i++)
if (dhcp_options[i].code == code) {
length = option_lengths[dhcp_options[i].flags & TYPE_MASK];
}
if (!length) {
DEBUG(LOG_ERR, "Could not add option 0x%02x", code);
return 0;
}
option[OPT_CODE] = code;
option[OPT_LEN] = length;
switch (length) {
case 1: *u8 = data; break;
case 2: *u16 = data; break;
case 4: *u32 = data; break;
}
memcpy(option + 2, &aligned, length);
return add_option_string(optionptr, option, 1);
}
/* find option 'code' in opt_list */
struct option_set *find_option(struct option_set *opt_list, char code)
{
while (opt_list && opt_list->data[OPT_CODE] < code)
opt_list = opt_list->next;
if (opt_list && opt_list->data[OPT_CODE] == code) return opt_list;
else return NULL;
}
/* add an option to the opt_list */
void attach_option(struct option_set **opt_list, struct dhcp_option *option, char *buffer, int length)
{
struct option_set *existing, *new, **curr;
/* add it to an existing option */
if ((existing = find_option(*opt_list, option->code))) {
DEBUG(LOG_INFO, "Attaching option %s to existing member of list", option->name);
if (option->flags & OPTION_LIST) {
if (existing->data[OPT_LEN] + length <= 255) {
existing->data = realloc(existing->data,
existing->data[OPT_LEN] + length + 2);
memcpy(existing->data + existing->data[OPT_LEN] + 2, buffer, length);
existing->data[OPT_LEN] += length;
} /* else, ignore the data, we could put this in a second option in the future */
} /* else, ignore the new data */
} else {
DEBUG(LOG_INFO, "Attaching option %s to list", option->name);
/* make a new option */
new = xmalloc(sizeof(struct option_set));
new->data = xmalloc(length + 2);
new->data[OPT_CODE] = option->code;
new->data[OPT_LEN] = length;
memcpy(new->data + 2, buffer, length);
curr = opt_list;
while (*curr && (*curr)->data[OPT_CODE] < option->code)
curr = &(*curr)->next;
new->next = *curr;
*curr = new;
}
}
[-- Attachment #6: packet.c --]
[-- Type: text/x-csrc, Size: 5422 bytes --]
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <features.h>
#if __GLIBC__ >=2 && __GLIBC_MINOR >= 1
#include <netpacket/packet.h>
#include <net/ethernet.h>
#else
#include <asm/types.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#endif
#include <errno.h>
#include "packet.h"
#include "dhcpd.h"
#include "options.h"
#include "common.h"
void init_header(struct dhcpMessage *packet, char type)
{
memset(packet, 0, sizeof(struct dhcpMessage));
switch (type) {
case DHCPDISCOVER:
case DHCPREQUEST:
case DHCPRELEASE:
case DHCPINFORM:
packet->op = BOOTREQUEST;
break;
case DHCPOFFER:
case DHCPACK:
case DHCPNAK:
packet->op = BOOTREPLY;
}
packet->htype = ETH_10MB;
packet->hlen = ETH_10MB_LEN;
packet->cookie = htonl(DHCP_MAGIC);
packet->options[0] = DHCP_END;
add_simple_option(packet->options, DHCP_MESSAGE_TYPE, type);
}
/* read a packet from socket fd, return -1 on read error, -2 on packet error */
int get_packet(struct dhcpMessage *packet, int fd)
{
int bytes;
int i;
const char broken_vendors[][8] = {
"MSFT 98",
""
};
char unsigned *vendor;
memset(packet, 0, sizeof(struct dhcpMessage));
bytes = read(fd, packet, sizeof(struct dhcpMessage));
if (bytes < 0) {
DEBUG(LOG_INFO, "couldn't read on listening socket, ignoring");
return -1;
}
if (ntohl(packet->cookie) != DHCP_MAGIC) {
LOG(LOG_ERR, "received bogus message, ignoring");
return -2;
}
DEBUG(LOG_INFO, "Received a packet");
if (packet->op == BOOTREQUEST && (vendor = get_option(packet, DHCP_VENDOR))) {
for (i = 0; broken_vendors[i][0]; i++) {
if (vendor[OPT_LEN - 2] == (uint8_t) strlen(broken_vendors[i]) &&
!strncmp(vendor, broken_vendors[i], vendor[OPT_LEN - 2])) {
DEBUG(LOG_INFO, "broken client (%s), forcing broadcast",
broken_vendors[i]);
packet->flags |= htons(BROADCAST_FLAG);
}
}
}
return bytes;
}
uint16_t checksum(void *addr, int count)
{
/* Compute Internet Checksum for "count" bytes
* beginning at location "addr".
*/
register int32_t sum = 0;
uint16_t *source = (uint16_t *) addr;
while (count > 1) {
/* This is the inner loop */
sum += *source++;
count -= 2;
}
/* Add left-over byte, if any */
if (count > 0) {
/* Make sure that the left-over byte is added correctly both
* with little and big endian hosts */
uint16_t tmp = 0;
*(uint8_t *) (&tmp) = * (uint8_t *) source;
sum += tmp;
}
/* Fold 32-bit sum to 16 bits */
while (sum >> 16)
sum = (sum & 0xffff) + (sum >> 16);
return ~sum;
}
/* Constuct a ip/udp header for a packet, and specify the source and dest hardware address */
int raw_packet(struct dhcpMessage *payload, uint32_t source_ip, int source_port,
uint32_t dest_ip, int dest_port, uint8_t *dest_arp, int ifindex)
{
int fd;
int result = -1;
struct sockaddr_ll dest;
struct udp_dhcp_packet packet;
int i;
if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) {
DEBUG(LOG_ERR, "socket call failed: %m");
return -1;
}
memset(&dest, 0, sizeof(dest));
memset(&packet, 0, sizeof(packet));
dest.sll_family = AF_PACKET;
dest.sll_protocol = htons(ETH_P_IP);
dest.sll_ifindex = ifindex;
dest.sll_halen = 6;
memcpy(dest.sll_addr, dest_arp, 6);
if (bind(fd, (struct sockaddr *)&dest, sizeof(struct sockaddr_ll)) < 0) {
DEBUG(LOG_ERR, "bind call failed: %m");
close(fd);
return -1;
}
packet.ip.protocol = IPPROTO_UDP;
packet.ip.saddr = source_ip;
packet.ip.daddr = dest_ip;
packet.udp.source = htons(source_port);
packet.udp.dest = htons(dest_port);
packet.udp.len = htons(sizeof(packet.udp) + sizeof(struct dhcpMessage)); /* cheat on the psuedo-header */
packet.ip.tot_len = packet.udp.len;
memcpy(&(packet.data), payload, sizeof(struct dhcpMessage));
packet.udp.check = checksum(&packet, sizeof(struct udp_dhcp_packet));
packet.ip.tot_len = htons(sizeof(struct udp_dhcp_packet));
packet.ip.ihl = sizeof(packet.ip) >> 2;
packet.ip.version = IPVERSION;
packet.ip.ttl = IPDEFTTL;
packet.ip.check = checksum(&(packet.ip), sizeof(packet.ip));
LOG(LOG_INFO, "raw_packet: send %d times", server_config.send_mult);
for (i = 0; i < server_config.send_mult; i++) {
result = sendto(fd, &packet, sizeof(struct udp_dhcp_packet), 0, (struct sockaddr *) &dest, sizeof(dest));
if (result <= 0) {
DEBUG(LOG_ERR, "write on socket failed: %m");
}
}
close(fd);
return result;
}
/* Let the kernel do all the work for packet generation */
int kernel_packet(struct dhcpMessage *payload, uint32_t source_ip, int source_port,
uint32_t dest_ip, int dest_port)
{
int n = 1;
int fd, result;
struct sockaddr_in client;
if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
return -1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(n)) == -1)
return -1;
memset(&client, 0, sizeof(client));
client.sin_family = AF_INET;
client.sin_port = htons(source_port);
client.sin_addr.s_addr = source_ip;
if (bind(fd, (struct sockaddr *)&client, sizeof(struct sockaddr)) == -1)
return -1;
memset(&client, 0, sizeof(client));
client.sin_family = AF_INET;
client.sin_port = htons(dest_port);
client.sin_addr.s_addr = dest_ip;
if (connect(fd, (struct sockaddr *)&client, sizeof(struct sockaddr)) == -1)
return -1;
result = write(fd, payload, sizeof(struct dhcpMessage));
close(fd);
return result;
}
[-- Attachment #7: socket.c --]
[-- Type: text/x-csrc, Size: 4133 bytes --]
/*
* socket.c -- DHCP server client/server socket creation
*
* udhcp client/server
* Copyright (C) 1999 Matthew Ramsay <matthewr@moreton.com.au>
* Chris Trew <ctrew@moreton.com.au>
*
* Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <errno.h>
#include <features.h>
#if __GLIBC__ >=2 && __GLIBC_MINOR >= 1
#include <netpacket/packet.h>
#include <net/ethernet.h>
#else
#include <asm/types.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#endif
#include "socket.h"
#include "common.h"
int read_interface(char *interface, int *ifindex, uint32_t *addr, uint8_t *arp)
{
int fd;
struct ifreq ifr;
struct sockaddr_in *our_ip;
memset(&ifr, 0, sizeof(struct ifreq));
if((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) >= 0) {
ifr.ifr_addr.sa_family = AF_INET;
strcpy(ifr.ifr_name, interface);
if (addr) {
if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
our_ip = (struct sockaddr_in *) &ifr.ifr_addr;
*addr = our_ip->sin_addr.s_addr;
DEBUG(LOG_INFO, "%s (our ip) = %s", ifr.ifr_name, inet_ntoa(our_ip->sin_addr));
} else {
LOG(LOG_ERR, "SIOCGIFADDR failed, is the interface up and configured?: %m");
return -1;
}
}
if (ioctl(fd, SIOCGIFINDEX, &ifr) == 0) {
DEBUG(LOG_INFO, "adapter index %d", ifr.ifr_ifindex);
*ifindex = ifr.ifr_ifindex;
} else {
LOG(LOG_ERR, "SIOCGIFINDEX failed!: %m");
return -1;
}
if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) {
memcpy(arp, ifr.ifr_hwaddr.sa_data, 6);
DEBUG(LOG_INFO, "adapter hardware address %02x:%02x:%02x:%02x:%02x:%02x",
arp[0], arp[1], arp[2], arp[3], arp[4], arp[5]);
} else {
LOG(LOG_ERR, "SIOCGIFHWADDR failed!: %m");
return -1;
}
} else {
LOG(LOG_ERR, "socket failed!: %m");
return -1;
}
close(fd);
return 0;
}
int listen_socket(uint32_t ip, int port, char *inf)
{
struct ifreq interface;
int fd;
struct sockaddr_in addr;
int n = 1;
DEBUG(LOG_INFO, "Opening listen socket on 0x%08x:%d %s", ip, port, inf);
if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
DEBUG(LOG_ERR, "dhcp socket call failed: %m");
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = ip;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(n)) == -1) {
close(fd);
return -1;
}
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char *) &n, sizeof(n)) == -1) {
close(fd);
return -1;
}
strncpy(interface.ifr_ifrn.ifrn_name, inf, IFNAMSIZ);
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,(char *)&interface, sizeof(interface)) < 0) {
close(fd);
return -1;
}
if (bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
close(fd);
return -1;
}
return fd;
}
int arp_socket(char *inf, int ifindex)
{
struct sockaddr_ll sll;
int fd;
DEBUG(LOG_INFO, "Opening arp socket on %s", inf);
if ((fd = socket(PF_PACKET, SOCK_DGRAM, 0)) < 0) {
DEBUG(LOG_ERR, "arp socket call failed: %m");
return -1;
}
memset(&sll, 0, sizeof(sll));
sll.sll_family = AF_PACKET;
sll.sll_protocol = htons(ETH_P_ARP);
sll.sll_ifindex = ifindex;
if (bind(fd, (struct sockaddr*)&sll, sizeof(sll)) < 0) {
close(fd);
DEBUG(LOG_ERR, "arp bind call failed: %m");
return -1;
}
return fd;
}
[-- Attachment #8: ippnpadd --]
[-- Type: text/plain, Size: 1584 bytes --]
#!/bin/ash
# $1 mac
# $2 gwip
# $3 leaseip
# $4 clientip
# $5 clientip +/- 1
# $6 interface
# $1 mac
# $2 leaseip
# $3 clientip
# $4 interface
. /system/data/network.cfg
if [ "$#" = "6" ]; then
mac=$1
gwip=$2
leaseip=$3
fixip=$4
fixip1=$5
interface=$6
else if [ "$#" = "4" ]; then
mac=$1
gwip=`echo $2 | awk -F \. '/./ { print $1 "." $2 "." $3 ".1" }'`
leaseip=$2
fixip=$3
fixip1=`echo $3 | awk -F \. '/./ { if ($4 == 1) print $1 "." $2 "." $3 "." $4 + 1; else print $1 "." $2 "." $3 "." $4 - 1 }'`
interface=$4
else
logger ippnpadd wrong number of params
exit
fi
fi
# check reserved subnet - if yes, do nothing (allow switches and APs to be managed from gateway
rsvsubnet=`echo $NET_LANIPADDRESS | awk -F \. '/./ { print $1 "." $2 "." $3 }'`
clientsubnet=`echo $fixip | awk -F \. '/./ { print $1 "." $2 "." $3 }'`
grep -i $fixip /system/data/ipdevices.cfg
if [ "$?" = 0 -o "$rsvsubnet" = "$clientsubnet" ]; then
logger ippnpadd Reserved subnet request dropped for $fixip
exit
fi
lanprefix=`echo $NET_LANLEASESTART | awk -F \. '/./ { print $1 "." $2 }'`
fixip1=$lanprefix.0.1
logger ippnpadd $mac $gwip $leaseip $fixip $fixip1 $interface
arptables -A OUTPUT -o $interface -d $leaseip -j mangle --mangle-ip-d $fixip --mangle-ip-s $fixip1
arptables -A INPUT -i $interface -s $fixip -j mangle --mangle-ip-s $leaseip --mangle-ip-d $gwip
iptables -t mangle -I PREROUTING -i $interface -s $fixip -j SADDR --to-source $leaseip
iptables -t mangle -I POSTROUTING -o $interface -d $leaseip -j DADDR --to-dest $fixip
dhcpd.sh dhcprequest $mac $leaseip $interface IPPNP
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2008-04-15 12:47 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20080414071710.C0E061802C4D8@sovereign.computergmbh.de>
2008-04-14 10:20 ` AW: Add new target in mangle table Jan Engelhardt
2008-04-14 15:44 ` manuprivat
2008-04-14 16:27 ` Jan Engelhardt
2008-04-14 16:34 ` manuprivat
2008-04-14 16:58 ` Jan Engelhardt
2008-04-15 8:06 ` Manu
2008-04-15 8:10 ` Manu
2008-04-15 8:35 ` manuprivat
2008-04-15 8:46 ` Jan Engelhardt
2008-04-15 9:20 ` manuel scheub
2008-04-15 9:52 ` Jan Engelhardt
2008-04-15 12:47 ` manuel scheub
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.