Skip to content

Commit

Permalink
Merge pull request #1 from RoadRunnr/master
Browse files Browse the repository at this point in the history
make it into a working server
  • Loading branch information
tonyrog committed Feb 12, 2015
2 parents d90f356 + f403913 commit 6153a8a
Show file tree
Hide file tree
Showing 14 changed files with 362 additions and 213 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
*~
*.[oa]
*.beam
/ebin/*.app
/priv/*.so

tetrapak/.local.cache

1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Ruslan Babayev <[email protected]>
Andreas Schultz <[email protected]>
Empty file removed README
Empty file.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# dhcp

This is DHCP Server in Erlang for running on Linux.

The Linux dependency comes mostly from the use of a special ioctl to inject ARP information into the kernel. The alternative to that would be to use raw packet socket, but those are not supported in Erlang.

The bind-to-interface socket option is also Linux specific, but the server could work without it.

## Requirements

* Linux
* Erlang (>= R17, older probably works as well)
19 changes: 19 additions & 0 deletions c_src/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
PRIVDIR := ../priv

LD ?= ld
CC ?= gcc
RM ?= rm

CFLAGS ?= -O2

override CFLAGS += -std=gnu99 -Wall -fpic
override LDFLAGS += -shared -fpic

all : $(PRIVDIR)/dhcp_server.so

$(PRIVDIR)/dhcp_server.so : dhcp_server.o
$(CC) $(LDFLAGS) -o $@ $^

clean:
$(RM) -f $(PRIVDIR)/dhcp_server.so dhcp_server.o

88 changes: 88 additions & 0 deletions c_src/dhcp_server.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
*
* Erlang ioctl wrapper to inject ARP entries to kernel
*
* Copyright (c) 2011-2012 by Travelping GmbH <[email protected]>
* Copyright (C) <year> <name of author>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/

#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <netinet/in.h>

#include <erl_nif.h>
#include "erl_driver.h" // for erl_errno_id

static ERL_NIF_TERM atom_error;
static ERL_NIF_TERM atom_ok;

static ERL_NIF_TERM arp_inject_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
struct arpreq arp;
struct sockaddr_in *in;

ErlNifBinary ip;
int htype;
ErlNifBinary addr;
ErlNifBinary ifname;
int fd;

if (!enif_inspect_binary(env, argv[0], &ifname)
|| ifname.size > 16
|| !enif_inspect_binary(env, argv[1], &ip)
|| ip.size != 4
|| !enif_get_int(env, argv[2], &htype)
|| !enif_inspect_binary(env, argv[3], &addr)
|| addr.size > 16
|| !enif_get_int(env, argv[4], &fd))
return enif_make_badarg(env);

memset(&arp, 0, sizeof(arp));
in = (struct sockaddr_in *)&arp.arp_pa;
in->sin_family = AF_INET;
memcpy(&in->sin_addr.s_addr, ip.data, 4);

arp.arp_ha.sa_family = htype;
memcpy(arp.arp_ha.sa_data, addr.data, addr.size);
memcpy(arp.arp_dev, ifname.data, ifname.size);
arp.arp_flags = ATF_COM;

if (ioctl(fd, SIOCSARP, &arp) < 0) {
return enif_make_tuple2(env, atom_error, enif_make_atom(env, erl_errno_id(errno)));
}

return atom_ok;
}

static ErlNifFunc nif_funcs[] = {
{"arp_inject_nif", 5, arp_inject_nif}
};

static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
{
atom_error = enif_make_atom(env,"error");
atom_ok = enif_make_atom(env,"ok");

return 0;
}

ERL_NIF_INIT(dhcp_server, nif_funcs, load, NULL, NULL, NULL)
82 changes: 23 additions & 59 deletions priv/dhcp.conf
Original file line number Diff line number Diff line change
@@ -1,59 +1,23 @@
%%%
%%% Sample configuration file for dhcp
%%%

%%% Global configuration
{server_id, {47,80,19,32}}.
{next_server, {47,80,19,32}}.
{authoritative, true}.
{log_facility, local7}.
{logfile, "/var/log/dhcp.log"}.
{lease_file, "/var/run/dhcp_leases.dets"}.

%%% Hub subnet
{subnet,
{192,168,1,0}, %% Network
{255,255,255,0}, %% Netmask
{{192,168,1,5},{192,168,1,10}}, %% Range
[{1,{255,255,255,0}}, %% Subnet Mask
{28,{192,168,1,255}}, %% Broadcast Address
{3,[{192,168,1,1}]}, %% Routers
{15,"us.nortel.com"}, %% Domain Name
{6,[{47,80,19,33}]}, %% Domain Name Servers
{51,3600}]}. %% Address Lease Time

%%% Red subnet
{subnet,
{192,168,10,0}, %% Network
{255,255,255,0}, %% Netmask
{{192,168,10,5},{192,168,10,10}}, %% Range
[{1,{255,255,255,0}}, %% Subnet Mask
{28,{192,168,10,255}}, %% Broadcast Address
{3,[{192,168,10,1}]}, %% Routers
{15,"us.nortel.com"}, %% Domain Name
{6,[{47,80,19,33}]}, %% Domain Name Servers
{51,3600}]}. %% Address Lease Time

%%% Yellow subnet
{subnet,
{192,168,20,0}, %% Network
{255,255,255,0}, %% Netmask
{{192,168,20,5},{192,168,20,10}}, %% Range
[{1,{255,255,255,0}}, %% Subnet Mask
{28,{192,168,20,255}}, %% Broadcast Address
{3,[{192,168,20,1}]}, %% Routers
{15,"us.nortel.com"}, %% Domain Name
{6,[{47,80,19,30}]}, %% Domain Name Servers
{51,7200}]}. %% Address Lease Time

%%% Green subnet
{subnet,
{192,168,30,0}, %% Network
{255,255,255,0}, %% Netmask
{{192,168,30,5},{192,168,30,10}}, %% Range
[{1,{255,255,255,0}}, %% Subnet Mask
{28,{192,168,30,255}}, %% Broadcast Address
{3,[{192,168,30,1}]}, %% Routers
{15,"us.nortel.com"}, %% Domain Name
{6,[{47,80,19,30}]}, %% Domain Name Servers
{51,86400}]}. %% Address Lease Time
%%%
%%% Sample configuration file for dhcp
%%%

%%% Global configuration
{server_id, {172,20,48,1}}.
%%{next_server, {47,80,19,32}}.
{interface, <<"tap0">>}.
{authoritative, true}.
{lease_file, "/var/run/dhcp_leases.dets"}.
{netns, "/var/run/netns/core"}.

%%% Hub subnet
{subnet,
{172,20,48,0}, %% Network
{255,255,255,0}, %% Netmask
{{172,20,48,5},{172,20,48,100}}, %% Range
[{1,{255,255,255,0}}, %% Subnet Mask
{28,{172,20,48,255}}, %% Broadcast Address
{3,[{192,20,48,1}]}, %% Routers
{15,"wlan"}, %% Domain Name
{6,[{172,20,48,1}]}, %% Domain Name Servers
{51,3600}]}. %% Address Lease Time
2 changes: 1 addition & 1 deletion src/dhcp.app.src
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
{vsn, git},
{modules, [dhcp_app, dhcp_sup, dhcp_server, dhcp_alloc, dhcp_lib]},
{registered, [dhcp_sup, dhcp_server, dhcp_alloc]},
{applications, [kernel, stdlib]},
{applications, [kernel, stdlib, lager]},
{mod, {dhcp_app, []}}
]}.
7 changes: 4 additions & 3 deletions src/dhcp_app.erl
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,16 @@
%% Function: start(Type, StartArgs) -> {ok, Pid} |
%% {ok, Pid, State} |
%% {error, Reason}
%% Description: This function is called whenever an application
%% Description: This function is called whenever an application
%% is started using application:start/1,2, and should start the processes
%% of the application. If the application is structured according to the
%% OTP design principles as a supervision tree, this means starting the
%% top supervisor of the tree.
%%--------------------------------------------------------------------
start(_Type, _StartArgs) ->
lager:set_loglevel(lager_console_backend, debug),
case dhcp_sup:start_link() of
{ok, Pid} ->
{ok, Pid} ->
{ok, Pid};
Error ->
Error
Expand All @@ -37,7 +38,7 @@ start(_Type, _StartArgs) ->
%% Function: stop(State) -> void()
%% Description: This function is called whenever an application
%% has stopped. It is intended to be the opposite of Module:start/2 and
%% should do any necessary cleaning up. The return value is ignored.
%% should do any necessary cleaning up. The return value is ignored.
%%--------------------------------------------------------------------
stop(_State) ->
ok.
Expand Down
5 changes: 3 additions & 2 deletions src/dhcp_lib.erl
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
%%%-------------------------------------------------------------------
%%% File : dhcp_lib.erl
%%% Author : Ruslan Babayev <[email protected]>
%%% Description :
%%% Description :
%%%
%%% Created : 17 Apr 2006 by Ruslan Babayev <[email protected]>
%%%-------------------------------------------------------------------
-module(dhcp_lib).

%% API
-export([decode/1, encode/1]).
-export([ip_to_binary/1, eth_to_binary/1]).
-import(lists, [keymember/3, keysearch/3, keyreplace/4]).
-include("dhcp.hrl").

%%====================================================================
%% API
%%====================================================================
%%--------------------------------------------------------------------
%% Function:
%% Function:
%% Description:
%%--------------------------------------------------------------------
decode(<<Op, Htype, Hlen, Hops, Xid:32, Secs:16, Flags:16,
Expand Down
Loading

0 comments on commit 6153a8a

Please sign in to comment.