提交 95586a13 编写于 作者: K Kozlov Dmitry

ipoe: implemented dhcp relay

上级 ff80a772
......@@ -45,6 +45,7 @@ shared=0
ifcfg=1
mode=L2
start=dhcpv4
#relay=10.10.10.10
#attr-dhcp-client-ip=DHCP-Client-IP-Address
#attr-dhcp-router-ip=DHCP-Router-IP-Address
#attr-dhcp-mask=DHCP-Mask
......
......@@ -229,8 +229,15 @@ Specifies default value for per-interface
.B ifcfg
parameter.
.TP
.BI "relay=" ipv4_address
Specifies default value for per-interface
.B relay
parameter.
.TP
.BI "interface=" [re:]name[,mode=L2|L3][,shared=0|1][,start=dhcpv4|up]
.BI "" [,range=x.x.x.x/mask][,ifcfg=0|1]
.BI "" [,relay=x.x.x.x]
.BI "" [,giaddr=x.x.x.x]
.br
Specifies interface to listen dhcp or unclassified packets. You may specify multiple
.B interface
......@@ -267,6 +274,16 @@ parameter specifies local range of ip address to give to dhcp clients. First IP
The
.B ifcfg
parameter specifies whether accel-ppp should add router IP address and route to client to interface or it is explicitly configured.
.br
The
.B relay
parameter specifies DHCPv4 relay IP address to pass requests to. If specified
.B giaddr
is also needed.
.br
The
.B giaddr
parameter specifies relay agent IP address.
.TP
.BI "local-net=" x.x.x.x/mask
Specifies networks from which packets will be treated as unclassified. You may specify multiple local-net options.
......
......@@ -15,8 +15,7 @@
#define IPOE_TAG_HWADDR 1
#define IPOE_TAG_CLIENT_ID 2
#define IPOE_TAG_AGENT_CIRCUIT_ID 3
#define IPOE_TAG_AGENT_REMOTE_ID 4
#define IPOE_TAG_RELAY_AGENT 3
#define IPOE_TAG_XID 5
#define IPOE_TAG_GIADDR 6
#define IPOE_TAG_CALLING_SID 7
......@@ -26,12 +25,16 @@
#define IPOE_TAG_YIADDR 11
#define IPOE_TAG_SIADDR 12
#define IPOE_TAG_MASK 13
#define IPOE_TAG_RELAY_SERVER_ID 14
#define IPOE_TAG_LEASE_TIME 15
#define IPOE_TAG_IFINDEX 100
#define IPOE_FLAG_IFCFG 0x01
#define IPOE_FLAG_DHCP_ADDR 0x02
#define IPOE_FLAG_L4_REDIR 0x04
#define IPOE_FLAG_IFCFG 0x01
#define IPOE_FLAG_DHCP_ADDR 0x02
#define IPOE_FLAG_RELAY_ADDR 0x04
#define IPOE_FLAG_L4_REDIR 0x08
#define IPOE_FLAG_L4_REDIR_SET 0x10
#define add_tag(id, data, size) if (!backup_add_tag(m, id, 0, data, size)) return -1;
#define add_tag_i(id, data, size) if (!backup_add_tag(m, id, 1, data, size)) return -1;
......@@ -52,8 +55,14 @@ static int session_save(struct ap_session *ses, struct backup_mod *m)
if (conn->dhcp_addr)
flags |= IPOE_FLAG_DHCP_ADDR;
if (conn->relay_addr)
flags |= IPOE_FLAG_RELAY_ADDR;
if (conn->l4_redirect)
flags |= IPOE_FLAG_L4_REDIR;
if (conn->l4_redirect_set)
flags |= IPOE_FLAG_L4_REDIR_SET;
add_tag(IPOE_TAG_HWADDR, conn->hwaddr, 6);
add_tag(IPOE_TAG_CALLING_SID, ses->ctrl->calling_station_id, strlen(ses->ctrl->calling_station_id));
......@@ -64,16 +73,16 @@ static int session_save(struct ap_session *ses, struct backup_mod *m)
add_tag(IPOE_TAG_SIADDR, &conn->siaddr, 4);
add_tag(IPOE_TAG_MASK, &conn->mask, 1);
add_tag(IPOE_TAG_FLAGS, &flags, 4);
add_tag(IPOE_TAG_RELAY_SERVER_ID, &conn->relay_server_id, 4);
add_tag(IPOE_TAG_LEASE_TIME, &conn->lease_time, 4);
add_tag(IPOE_TAG_IFNAME, conn->serv->ifname, strlen(conn->serv->ifname) + 1);
if (conn->client_id)
add_tag(IPOE_TAG_CLIENT_ID, conn->client_id->data, conn->client_id->len);
if (conn->agent_circuit_id)
add_tag(IPOE_TAG_AGENT_CIRCUIT_ID, conn->agent_circuit_id->data, conn->agent_circuit_id->len);
if (conn->agent_circuit_id)
add_tag(IPOE_TAG_AGENT_REMOTE_ID, conn->agent_remote_id->data, conn->agent_remote_id->len);
add_tag(IPOE_TAG_IFNAME, conn->serv->ifname, strlen(conn->serv->ifname) + 1);
if (conn->relay_agent)
add_tag(IPOE_TAG_RELAY_AGENT, conn->relay_agent->data, conn->relay_agent->len);
add_tag_i(IPOE_TAG_IFINDEX, &conn->ifindex, 4);
return 0;
......@@ -87,9 +96,9 @@ static int session_restore(struct ap_session *ses, struct backup_mod *m)
return 0;
}
static void set_dhcpv4_opt(struct dhcp_opt **opt, struct backup_tag *t, uint8_t **ptr)
static void set_dhcpv4_opt(struct dhcpv4_option **opt, struct backup_tag *t, uint8_t **ptr)
{
*opt = (struct dhcp_opt *)(*ptr);
*opt = (struct dhcpv4_option *)(*ptr);
(*opt)->len = t->size;
memcpy((*opt)->data, t->data, t->size);
(*ptr) += sizeof(**opt) + t->size;
......@@ -112,9 +121,8 @@ static struct ap_session *ctrl_restore(struct backup_mod *m)
list_for_each_entry(t, &m->tag_list, entry) {
switch(t->id) {
case IPOE_TAG_CLIENT_ID:
case IPOE_TAG_AGENT_CIRCUIT_ID:
case IPOE_TAG_AGENT_REMOTE_ID:
dlen += sizeof(struct dhcp_opt) + t->size;
case IPOE_TAG_RELAY_AGENT:
dlen += sizeof(struct dhcpv4_option) + t->size;
break;
case IPOE_TAG_IFNAME:
ifname = t;
......@@ -162,11 +170,9 @@ static struct ap_session *ctrl_restore(struct backup_mod *m)
case IPOE_TAG_CLIENT_ID:
set_dhcpv4_opt(&ses->client_id, t, &ptr);
break;
case IPOE_TAG_AGENT_CIRCUIT_ID:
set_dhcpv4_opt(&ses->agent_circuit_id, t, &ptr);
break;
case IPOE_TAG_AGENT_REMOTE_ID:
set_dhcpv4_opt(&ses->agent_remote_id, t, &ptr);
case IPOE_TAG_RELAY_AGENT:
set_dhcpv4_opt(&ses->relay_agent, t, &ptr);
dhcpv4_parse_opt82(ses->relay_agent, &ses->agent_circuit_id, &ses->agent_remote_id);
break;
case IPOE_TAG_IFINDEX:
ses->ifindex = *(uint32_t *)t->data;
......@@ -183,6 +189,12 @@ static struct ap_session *ctrl_restore(struct backup_mod *m)
case IPOE_TAG_FLAGS:
flags = *(uint32_t *)t->data;
break;
case IPOE_TAG_RELAY_SERVER_ID:
ses->relay_server_id = *(uint32_t *)t->data;
break;
case IPOE_TAG_LEASE_TIME:
ses->lease_time = *(uint32_t *)t->data;
break;
}
}
......@@ -194,8 +206,14 @@ static struct ap_session *ctrl_restore(struct backup_mod *m)
ses->dhcp_addr = 1;
}
if (flags & IPOE_FLAG_RELAY_ADDR)
ses->relay_addr = 1;
if (flags & IPOE_FLAG_L4_REDIR)
ses->l4_redirect = 1;
if (flags & IPOE_FLAG_L4_REDIR_SET && m->data->internal)
ses->l4_redirect = 1;
ses->serv = serv;
......
......@@ -25,13 +25,14 @@
#include "dhcpv4.h"
#define DHCP_SERV_PORT 67
#define DHCP_CLIENT_PORT 68
#define DHCP_MAGIC "\x63\x82\x53\x63"
#define BUF_SIZE 4096
struct dhcpv4_relay_ctx
{
struct list_head entry;
struct triton_context_t *ctx;
triton_event_func recv;
};
static int conf_verbose;
static in_addr_t conf_dns1;
......@@ -40,6 +41,8 @@ static in_addr_t conf_dns2;
static mempool_t pack_pool;
static mempool_t opt_pool;
static LIST_HEAD(relay_list);
static int dhcpv4_read(struct triton_md_handler_t *h);
static struct dhcpv4_iprange *parse_range(const char *str)
......@@ -228,11 +231,11 @@ void dhcpv4_free(struct dhcpv4_serv *serv)
_free(serv);
}
void dhcpv4_print_packet(struct dhcpv4_packet *pack, void (*print)(const char *fmt, ...))
void dhcpv4_print_packet(struct dhcpv4_packet *pack, int relay, void (*print)(const char *fmt, ...))
{
const char *msg_name[] = {"Discover", "Offer", "Request", "Decline", "Ack", "Nak", "Release", "Inform"};
print("[DHCPv4 %s xid=%x ", msg_name[pack->msg_type - 1], pack->hdr->xid);
print("[DHCPv4 %s%s xid=%x ", relay ? "relay " : "", msg_name[pack->msg_type - 1], pack->hdr->xid);
if (pack->hdr->ciaddr)
print("ciaddr=%i.%i.%i.%i ",
......@@ -276,41 +279,6 @@ void dhcpv4_print_packet(struct dhcpv4_packet *pack, void (*print)(const char *f
print("]\n");
}
static int parse_opt82(struct dhcpv4_packet *pack, struct dhcpv4_option *opt)
{
uint8_t *ptr = opt->data;
uint8_t *endptr = ptr + opt->len;
int type, len;
struct dhcpv4_option *opt1;
while (ptr < endptr) {
type = *ptr++;
len = *ptr++;
if (ptr + len > endptr)
return -1;
if (type == 1 || type == 2) {
opt1 = mempool_alloc(opt_pool);
if (!opt1) {
log_emerg("out of memory\n");
return -1;
}
opt1->type = type;
opt1->len = len;
opt1->data = ptr;
if (type == 1)
pack->agent_circuit_id = opt1;
else
pack->agent_remote_id = opt1;
}
ptr += len;
}
return 0;
}
static int dhcpv4_parse_packet(struct dhcpv4_packet *pack, int len)
{
struct dhcpv4_option *opt;
......@@ -321,9 +289,6 @@ static int dhcpv4_parse_packet(struct dhcpv4_packet *pack, int len)
log_warn("dhcpv4: short packet received\n");
return -1;
}
if (pack->hdr->op != DHCP_OP_REQUEST)
return -1;
if (pack->hdr->htype != 1)
return -1;
......@@ -342,8 +307,10 @@ static int dhcpv4_parse_packet(struct dhcpv4_packet *pack, int len)
continue;
}
if (*ptr == 0xff)
if (*ptr == 0xff) {
ptr++;
break;
}
opt = mempool_alloc(opt_pool);
if (!opt) {
......@@ -364,7 +331,9 @@ static int dhcpv4_parse_packet(struct dhcpv4_packet *pack, int len)
if (opt->type == 53)
pack->msg_type = opt->data[0];
else if (opt->type == 82)
parse_opt82(pack, opt);
pack->relay_agent = opt;
else if (opt->type == 62)
pack->client_id = opt;
else if (opt->type == 50)
pack->request_ip = *(uint32_t *)opt->data;
else if (opt->type == 54)
......@@ -377,6 +346,8 @@ static int dhcpv4_parse_packet(struct dhcpv4_packet *pack, int len)
if (dhcpv4_check_options(pack))
return -1;
pack->ptr = ptr;
/*if (conf_verbose) {
log_info2("recv ");
print_packet(pack, log_info2);
......@@ -398,12 +369,71 @@ static struct dhcpv4_packet *dhcpv4_packet_alloc()
pack->hdr = (struct dhcpv4_hdr *)pack->data;
pack->ptr = (uint8_t *)(pack->hdr + 1);
pack->refs = 1;
memcpy(pack->hdr->magic, DHCP_MAGIC, 4);
return pack;
}
void dhcpv4_packet_ref(struct dhcpv4_packet *pack)
{
__sync_add_and_fetch(&pack->refs, 1);
}
struct dhcpv4_option *dhcpv4_packet_find_opt(struct dhcpv4_packet *pack, int type)
{
struct dhcpv4_option *opt;
list_for_each_entry(opt, &pack->options, entry) {
if (opt->type == type)
return opt;
}
return NULL;
}
void dhcpv4_packet_free(struct dhcpv4_packet *pack)
{
struct dhcpv4_option *opt;
if (__sync_sub_and_fetch(&pack->refs, 1))
return;
while (!list_empty(&pack->options)) {
opt = list_entry(pack->options.next, typeof(*opt), entry);
list_del(&opt->entry);
mempool_free(opt);
}
mempool_free(pack);
}
int dhcpv4_parse_opt82(struct dhcpv4_option *opt, uint8_t **agent_circuit_id, uint8_t **agent_remote_id)
{
uint8_t *ptr = opt->data;
uint8_t *endptr = ptr + opt->len;
int type, len;
while (ptr < endptr) {
type = *ptr++;
len = *ptr++;
if (ptr + len > endptr)
return -1;
if (type == 1)
*agent_circuit_id = ptr - 1;
else if (type == 2)
*agent_remote_id = ptr - 1;
ptr += len;
}
return 0;
}
static int dhcpv4_read(struct triton_md_handler_t *h)
{
struct dhcpv4_packet *pack;
......@@ -433,12 +463,62 @@ static int dhcpv4_read(struct triton_md_handler_t *h)
dhcpv4_packet_free(pack);
continue;
}
if (pack->hdr->op != DHCP_OP_REQUEST) {
dhcpv4_packet_free(pack);
continue;
}
if (serv->recv)
serv->recv(serv, pack);
dhcpv4_packet_free(pack);
}
}
static int dhcpv4_relay_read(struct triton_md_handler_t *h)
{
struct dhcpv4_packet *pack;
struct dhcpv4_relay *r = container_of(h, typeof(*r), hnd);
int n;
struct dhcpv4_relay_ctx *c;
while (1) {
pack = dhcpv4_packet_alloc();
if (!pack) {
log_emerg("out of memory\n");
return 1;
}
n = read(h->fd, pack->data, BUF_SIZE);
if (n == -1) {
mempool_free(pack);
if (errno == EAGAIN)
return 0;
log_error("dhcpv4: recv: %s\n", strerror(errno));
continue;
}
if (dhcpv4_parse_packet(pack, n)) {
dhcpv4_packet_free(pack);
continue;
}
if (pack->hdr->op != DHCP_OP_REPLY) {
dhcpv4_packet_free(pack);
continue;
}
list_for_each_entry(c, &r->ctx_list, entry) {
dhcpv4_packet_ref(pack);
triton_context_call(c->ctx, c->recv, pack);
}
dhcpv4_packet_free(pack);
}
}
uint16_t ip_csum(uint16_t *buf, int len)
{
uint32_t sum=0;
......@@ -528,25 +608,6 @@ static int dhcpv4_send(struct dhcpv4_serv *serv, struct dhcpv4_packet *pack, in_
return dhcpv4_send_raw(serv, pack, saddr, daddr);
}
void dhcpv4_packet_free(struct dhcpv4_packet *pack)
{
struct dhcpv4_option *opt;
while (!list_empty(&pack->options)) {
opt = list_entry(pack->options.next, typeof(*opt), entry);
list_del(&opt->entry);
mempool_free(opt);
}
if (pack->agent_circuit_id)
mempool_free(pack->agent_circuit_id);
if (pack->agent_remote_id)
mempool_free(pack->agent_remote_id);
mempool_free(pack);
}
int dhcpv4_packet_add_opt(struct dhcpv4_packet *pack, int type, const void *data, int len)
{
struct dhcpv4_option *opt = mempool_alloc(opt_pool);
......@@ -571,7 +632,7 @@ int dhcpv4_packet_add_opt(struct dhcpv4_packet *pack, int type, const void *data
return 0;
}
int dhcpv4_send_reply(int msg_type, struct dhcpv4_serv *serv, struct dhcpv4_packet *req, uint32_t yiaddr, uint32_t siaddr, uint32_t mask, int lease_time)
int dhcpv4_send_reply(int msg_type, struct dhcpv4_serv *serv, struct dhcpv4_packet *req, uint32_t yiaddr, uint32_t siaddr, uint32_t mask, int lease_time, struct dhcpv4_packet *relay)
{
struct dhcpv4_packet *pack;
int val, r;
......@@ -579,6 +640,8 @@ int dhcpv4_send_reply(int msg_type, struct dhcpv4_serv *serv, struct dhcpv4_pack
in_addr_t dns1;
in_addr_t dns2;
} dns;
int dns_avail = 0;
struct dhcpv4_option *opt;
pack = dhcpv4_packet_alloc();
if (!pack) {
......@@ -589,7 +652,7 @@ int dhcpv4_send_reply(int msg_type, struct dhcpv4_serv *serv, struct dhcpv4_pack
memcpy(pack->hdr, req->hdr, sizeof(*req->hdr));
pack->hdr->op = DHCP_OP_REPLY;
pack->hdr->ciaddr = 0;
//pack->hdr->ciaddr = 0;
pack->hdr->yiaddr = yiaddr;
if (msg_type == DHCPOFFER)
pack->hdr->siaddr = siaddr;
......@@ -612,15 +675,28 @@ int dhcpv4_send_reply(int msg_type, struct dhcpv4_serv *serv, struct dhcpv4_pack
val = htonl(~((1 << (32 - mask)) - 1));
if (dhcpv4_packet_add_opt(pack, 1, &val, 4))
goto out_err;
if (relay) {
list_for_each_entry(opt, &relay->options, entry) {
if (opt->type == 53 || opt->type == 54 || opt->type == 51 || opt->type == 3 || opt->type == 1)
continue;
if (opt->type == 6)
dns_avail = 1;
if (dhcpv4_packet_add_opt(pack, opt->type, opt->data, opt->len))
goto out_err;
}
}
if (conf_dns1 && conf_dns2) {
dns.dns1 = conf_dns1;
dns.dns2 = conf_dns2;
if (dhcpv4_packet_add_opt(pack, 6, &dns, 8))
goto out_err;
} else if (conf_dns1) {
if (dhcpv4_packet_add_opt(pack, 6, &conf_dns1, 4))
goto out_err;
if (!dns_avail) {
if (conf_dns1 && conf_dns2) {
dns.dns1 = conf_dns1;
dns.dns2 = conf_dns2;
if (dhcpv4_packet_add_opt(pack, 6, &dns, 8))
goto out_err;
} else if (conf_dns1) {
if (dhcpv4_packet_add_opt(pack, 6, &conf_dns1, 4))
goto out_err;
}
}
*pack->ptr++ = 255;
......@@ -628,7 +704,7 @@ int dhcpv4_send_reply(int msg_type, struct dhcpv4_serv *serv, struct dhcpv4_pack
if (conf_verbose) {
pack->msg_type = msg_type;
log_ppp_info2("send ");
dhcpv4_print_packet(pack, log_ppp_info2);
dhcpv4_print_packet(pack, 0, log_ppp_info2);
}
r = dhcpv4_send(serv, pack, siaddr, yiaddr);
......@@ -669,7 +745,7 @@ int dhcpv4_send_nak(struct dhcpv4_serv *serv, struct dhcpv4_packet *req)
if (conf_verbose) {
pack->msg_type = DHCPNAK;
log_info2("send ");
dhcpv4_print_packet(pack, log_info2);
dhcpv4_print_packet(pack, 0, log_info2);
}
r = dhcpv4_send(serv, pack, 0, 0xffffffff);
......@@ -685,6 +761,196 @@ out_err:
return 0;
}
struct dhcpv4_relay *dhcpv4_relay_create(const char *_addr, const char *_giaddr, struct triton_context_t *ctx, triton_event_func recv)
{
struct dhcpv4_relay *r;
in_addr_t addr = inet_addr(_addr);
in_addr_t giaddr = inet_addr(_giaddr);
struct sockaddr_in raddr;
struct sockaddr_in laddr;
int sock = -1;
int f = 1;
struct dhcpv4_relay_ctx *c;
list_for_each_entry(r, &relay_list, entry) {
if (r->addr == addr && r->giaddr == giaddr)
goto found;
}
r = _malloc(sizeof(*r));
memset(r, 0, sizeof(*r));
INIT_LIST_HEAD(&r->ctx_list);
r->addr = addr;
r->giaddr = giaddr;
memset(&raddr, 0, sizeof(raddr));
raddr.sin_family = AF_INET;
raddr.sin_addr.s_addr = addr;
raddr.sin_port = htons(DHCP_SERV_PORT);
memset(&laddr, 0, sizeof(laddr));
laddr.sin_family = AF_INET;
laddr.sin_addr.s_addr = giaddr;
laddr.sin_port = htons(DHCP_SERV_PORT);
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (!sock) {
log_error("socket: %s\n", strerror(errno));
goto out_err;
}
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &f, sizeof(f)))
log_error("dhcpv4: setsockopt(SO_REUSEADDR): %s\n", strerror(errno));
if (bind(sock, &laddr, sizeof(laddr))) {
log_error("dhcpv4: relay: %s: bind: %s\n", _addr, strerror(errno));
goto out_err;
}
if (connect(sock, &raddr, sizeof(raddr))) {
log_error("dhcpv4: relay: %s: connect: %s\n", _addr, strerror(errno));
goto out_err;
}
fcntl(sock, F_SETFL, O_NONBLOCK);
fcntl(sock, F_SETFD, fcntl(sock, F_GETFD) | FD_CLOEXEC);
r->hnd.fd = sock;
r->hnd.read = dhcpv4_relay_read;
triton_context_register(&r->ctx, NULL);
triton_md_register_handler(ctx, &r->hnd);
triton_md_enable_handler(&r->hnd, MD_MODE_READ);
triton_context_wakeup(&r->ctx);
list_add_tail(&r->entry, &relay_list);
found:
c = _malloc(sizeof(*c));
c->ctx = ctx;
c->recv = recv;
list_add_tail(&c->entry, &r->ctx_list);
return r;
out_err:
if (sock != -1)
close(sock);
_free(r);
return NULL;
}
void dhcpv4_relay_free(struct dhcpv4_relay *r, struct triton_context_t *ctx)
{
struct dhcpv4_relay_ctx *c;
list_for_each_entry(c, &r->ctx_list, entry) {
if (c->ctx == ctx) {
list_del(&c->entry);
_free(c);
break;
}
}
if (list_empty(&r->ctx_list)) {
list_del(&r->entry);
triton_md_unregister_handler(&r->hnd);
close(r->hnd.fd);
triton_context_unregister(&r->ctx);
_free(r);
}
}
int dhcpv4_relay_send(struct dhcpv4_relay *relay, struct dhcpv4_packet *request, uint32_t server_id)
{
int n;
int len = request->ptr - request->data;
uint32_t giaddr = request->hdr->giaddr;
struct dhcpv4_option *opt = NULL;
uint32_t _server_id;
request->hdr->giaddr = relay->giaddr;
if (server_id) {
opt = dhcpv4_packet_find_opt(request, 54);
if (opt) {
_server_id = *(uint32_t *)opt->data;
*(uint32_t *)opt->data = server_id;
}
}
if (conf_verbose) {
log_ppp_info2("send ");
dhcpv4_print_packet(request, 1, log_ppp_info2);
}
n = write(relay->hnd.fd, request->data, len);
request->hdr->giaddr = giaddr;
if (opt)
*(uint32_t *)opt->data = _server_id;
if (n != len)
return -1;
return 0;
}
int dhcpv4_relay_send_release(struct dhcpv4_relay *relay, uint8_t *chaddr, uint32_t xid, uint32_t ciaddr,
struct dhcpv4_option *client_id, struct dhcpv4_option *relay_agent)
{
struct dhcpv4_packet *pack;
int n, len;
pack = dhcpv4_packet_alloc();
if (!pack) {
log_emerg("out of memory\n");
return -1;
}
memset(pack->hdr, 0, sizeof(*pack->hdr));
pack->msg_type = DHCPRELEASE;
pack->hdr->op = DHCP_OP_REQUEST;
pack->hdr->htype = 1;
pack->hdr->hlen = 6;
pack->hdr->ciaddr = ciaddr;
pack->hdr->giaddr = relay->giaddr;
pack->hdr->xid = xid;
memcpy(pack->hdr->magic, DHCP_MAGIC, 4);
memcpy(pack->hdr->chaddr, chaddr, 6);
if (dhcpv4_packet_add_opt(pack, 53, &pack->msg_type, 1))
goto out_err;
if (client_id && dhcpv4_packet_add_opt(pack, 61, client_id->data, client_id->len))
goto out_err;
if (relay_agent && dhcpv4_packet_add_opt(pack, 82, relay_agent->data, relay_agent->len))
goto out_err;
*pack->ptr = 255; pack->ptr++;
len = pack->ptr - pack->data;
if (conf_verbose) {
log_ppp_info2("send ");
dhcpv4_print_packet(pack, 1, log_ppp_info2);
}
n = write(relay->hnd.fd, pack->data, len);
dhcpv4_packet_free(pack);
return n == len ? 0 : -1;
out_err:
dhcpv4_packet_free(pack);
return -1;
}
int dhcpv4_get_ip(struct dhcpv4_serv *serv, uint32_t *yiaddr, uint32_t *siaddr, int *mask)
{
int i, k;
......
......@@ -9,6 +9,10 @@
#define __packed __attribute__((packed))
#define DHCP_SERV_PORT 67
#define DHCP_CLIENT_PORT 68
#define DHCP_MAGIC "\x63\x82\x53\x63"
#define DHCP_OP_REQUEST 1
#define DHCP_OP_REPLY 2
......@@ -53,11 +57,11 @@ struct dhcpv4_packet
struct dhcpv4_hdr *hdr;
struct list_head options;
struct dhcpv4_option *client_id;
struct dhcpv4_option *agent_circuit_id;
struct dhcpv4_option *agent_remote_id;
struct dhcpv4_option *relay_agent;
uint32_t request_ip;
uint32_t server_id;
int msg_type;
int volatile refs;
uint8_t *ptr;
uint8_t data[0];
};
......@@ -84,21 +88,40 @@ struct dhcpv4_serv
struct dhcpv4_iprange *range;
};
struct dhcpv4_relay
{
struct list_head entry;
struct triton_context_t ctx;
struct triton_md_handler_t hnd;
struct list_head ctx_list;
in_addr_t addr;
in_addr_t giaddr;
};
struct ap_session;
struct dhcpv4_serv *dhcpv4_create(struct triton_context_t *ctx, const char *ifname, const char *opt);
void dhcpv4_free(struct dhcpv4_serv *);
struct dhcpv4_relay *dhcpv4_relay_create(const char *addr, const char *giaddr, struct triton_context_t *ctx, triton_event_func recv);
void dhcpv4_relay_free(struct dhcpv4_relay *, struct triton_context_t *);
int dhcpv4_relay_send(struct dhcpv4_relay *relay, struct dhcpv4_packet *request, uint32_t server_id);
int dhcpv4_relay_send_release(struct dhcpv4_relay *relay, uint8_t *chaddr, uint32_t xid, uint32_t ciaddr,
struct dhcpv4_option *client_id, struct dhcpv4_option *relay_agent);
int dhcpv4_send_reply(int msg_type, struct dhcpv4_serv *serv, struct dhcpv4_packet *req, uint32_t yiaddr, uint32_t siaddr, uint32_t mask, int lease_time);
int dhcpv4_send_reply(int msg_type, struct dhcpv4_serv *serv, struct dhcpv4_packet *req, uint32_t yiaddr, uint32_t siaddr, uint32_t mask, int lease_time, struct dhcpv4_packet *relay_reply);
int dhcpv4_send_nak(struct dhcpv4_serv *serv, struct dhcpv4_packet *req);
void dhcpv4_packet_ref(struct dhcpv4_packet *pack);
struct dhcpv4_option *dhcpv4_packet_find_opt(struct dhcpv4_packet *pack, int type);
void dhcpv4_packet_free(struct dhcpv4_packet *pack);
int dhcpv4_check_options(struct dhcpv4_packet *);
void dhcpv4_print_options(struct dhcpv4_packet *, void (*)(const char *, ...));
void dhcpv4_print_packet(struct dhcpv4_packet *pack, void (*print)(const char *fmt, ...));
void dhcpv4_print_packet(struct dhcpv4_packet *pack, int relay, void (*print)(const char *fmt, ...));
int dhcpv4_parse_opt82(struct dhcpv4_option *opt, uint8_t **agent_circuit_id, uint8_t **agent_remote_id);
int dhcpv4_get_ip(struct dhcpv4_serv *serv, uint32_t *yiaddr, uint32_t *siaddr, int *mask);
void dhcpv4_put_ip(struct dhcpv4_serv *serv, uint32_t ip);
......
此差异已折叠。
......@@ -18,6 +18,7 @@ struct ipoe_serv
struct list_head sessions;
struct list_head addr_list;
struct dhcpv4_serv *dhcpv4;
struct dhcpv4_relay *dhcpv4_relay;
pthread_mutex_t lock;
int opt_mode;
int opt_shared:1;
......@@ -27,12 +28,6 @@ struct ipoe_serv
int need_close:1;
};
struct dhcp_opt
{
uint8_t len;
uint8_t data[0];
};
struct ipoe_session
{
struct list_head entry;
......@@ -42,20 +37,26 @@ struct ipoe_session
struct ap_ctrl ctrl;
struct ap_session ses;
uint8_t hwaddr[6];
struct dhcp_opt *client_id;
struct dhcp_opt *agent_circuit_id;
struct dhcp_opt *agent_remote_id;
struct dhcpv4_option *client_id;
struct dhcpv4_option *relay_agent;
uint8_t *agent_circuit_id;
uint8_t *agent_remote_id;
uint32_t xid;
uint32_t giaddr;
uint32_t yiaddr;
uint32_t siaddr;
uint32_t relay_server_id;
int mask;
int lease_time;
uint8_t *data;
struct dhcpv4_packet *dhcpv4_request;
struct dhcpv4_packet *dhcpv4_relay_reply;
int ifindex;
int ifcfg:1;
int dhcp_addr:1;
int relay_addr:1;
int l4_redirect:1;
int l4_redirect_set:1;
};
struct ipoe_session_info
......
......@@ -146,7 +146,7 @@ static int packet4_agent_circuit_id(lua_State *L)
return 0;
if (ses->agent_circuit_id)
lua_pushlstring(L, (char *)ses->agent_circuit_id->data, ses->agent_circuit_id->len);
lua_pushlstring(L, (char *)(ses->agent_circuit_id + 1), *ses->agent_circuit_id);
else
lua_pushnil(L);
......@@ -161,7 +161,7 @@ static int packet4_agent_remote_id(lua_State *L)
return 0;
if (ses->agent_remote_id)
lua_pushlstring(L, (char *)ses->agent_remote_id->data, ses->agent_remote_id->len);
lua_pushlstring(L, (char *)(ses->agent_remote_id + 1), *ses->agent_remote_id);
else
lua_pushnil(L);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册