diff options
author | xebd <xeb@mail.ru> | 2019-02-06 08:47:48 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-06 08:47:48 +0300 |
commit | 73792150c2ef5ddfc978f8f1aa0055b596db4f1c (patch) | |
tree | 8148e2fd466dd1a783303a2eda930d61c423f28b | |
parent | 1e2fa0927607a94b7e02d0ca3fd18eb090822de9 (diff) | |
parent | 7bea60cca67a9f6560ae5e11fd1edae8f81b857c (diff) | |
download | accel-ppp-73792150c2ef5ddfc978f8f1aa0055b596db4f1c.tar.gz accel-ppp-73792150c2ef5ddfc978f8f1aa0055b596db4f1c.zip |
Merge pull request #69 from themiron/ipoe-dhcp-radius-fix
ipoe: group dhcp options & wins support
-rw-r--r-- | accel-pppd/ctrl/ipoe/dhcpv4.c | 94 | ||||
-rw-r--r-- | accel-pppd/ctrl/ipoe/dhcpv4.h | 1 |
2 files changed, 75 insertions, 20 deletions
diff --git a/accel-pppd/ctrl/ipoe/dhcpv4.c b/accel-pppd/ctrl/ipoe/dhcpv4.c index 8a395ea8..9427e142 100644 --- a/accel-pppd/ctrl/ipoe/dhcpv4.c +++ b/accel-pppd/ctrl/ipoe/dhcpv4.c @@ -38,6 +38,8 @@ struct dhcpv4_relay_ctx { static int conf_verbose; static in_addr_t conf_dns1; static in_addr_t conf_dns2; +static in_addr_t conf_wins1; +static in_addr_t conf_wins2; static mempool_t pack_pool; static mempool_t opt_pool; @@ -693,13 +695,11 @@ static inline int dhcpv4_packet_add_opt_u32(struct dhcpv4_packet *pack, int type int dhcpv4_send_reply(int msg_type, struct dhcpv4_serv *serv, struct dhcpv4_packet *req, uint32_t yiaddr, uint32_t siaddr, uint32_t router, uint32_t mask, int lease_time, int renew_time, struct dhcpv4_packet *relay) { struct dhcpv4_packet *pack; - int val, r; - struct dns { - in_addr_t dns1; - in_addr_t dns2; - } dns; - int dns_avail = 0; struct dhcpv4_option *opt; + in_addr_t addr[2]; + int dns_avail = 0; + int wins_avail = 0; + int val, r; pack = dhcpv4_packet_alloc(); if (!pack) { @@ -743,23 +743,31 @@ int dhcpv4_send_reply(int msg_type, struct dhcpv4_serv *serv, struct dhcpv4_pack list_for_each_entry(opt, &relay->options, entry) { if (opt->type == 53 || opt->type == 54 || opt->type == 51 || opt->type == 58 || opt->type == 1 || (opt->type == 3 && router)) continue; - if (opt->type == 6) + else if (opt->type == 6) dns_avail = 1; + else if (opt->type == 44) + wins_avail = 1; if (dhcpv4_packet_add_opt(pack, opt->type, opt->data, opt->len)) 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; - } + if (conf_dns1) + addr[dns_avail++] = conf_dns1; + if (conf_dns2) + addr[dns_avail++] = conf_dns2; + if (dns_avail && dhcpv4_packet_add_opt(pack, 6, addr, dns_avail * sizeof(addr[0]))) + goto out_err; + } + + if (!wins_avail) { + if (conf_wins1) + addr[wins_avail++] = conf_wins1; + if (conf_wins2) + addr[wins_avail++] = conf_wins2; + if (wins_avail && dhcpv4_packet_add_opt(pack, 44, addr, wins_avail * sizeof(addr[0]))) + goto out_err; } *pack->ptr++ = 255; @@ -1146,8 +1154,9 @@ struct dhcpv4_packet *dhcpv4_clone_radius(struct rad_packet_t *rad) { struct dhcpv4_packet *pkt = dhcpv4_packet_alloc(); uint8_t *ptr, *endptr; - struct dhcpv4_option *opt; + struct dhcpv4_option *opt, *next; struct rad_attr_t *attr; + struct list_head *list; if (!pkt) return NULL; @@ -1166,20 +1175,57 @@ struct dhcpv4_packet *dhcpv4_clone_radius(struct rad_packet_t *rad) log_emerg("out of memory\n"); goto out; } + memset(opt, 0, sizeof(*opt)); + INIT_LIST_HEAD(&opt->list); opt->type = attr->attr->id; opt->len = attr->len; - opt->data = ptr; - memcpy(ptr, attr->raw, attr->len); + opt->data = attr->raw; ptr += attr->len; - list_add_tail(&opt->entry, &pkt->options); + list = &pkt->options; + if (attr->attr->array) { + list_for_each_entry(next, &pkt->options, entry) { + if (next->type == opt->type) { + list = &next->list; + break; + } + } + } + + list_add_tail(&opt->entry, list); + } + } + + ptr = pkt->data; + + list_for_each_entry(opt, &pkt->options, entry) { + memcpy(ptr, opt->data, opt->len); + opt->data = ptr; + ptr += opt->len; + + while (!list_empty(&opt->list)) { + next = list_entry(opt->list.next, typeof(*next), entry); + memcpy(ptr, next->data, next->len); + opt->len += next->len; + ptr += next->len; + + list_del(&next->entry); + mempool_free(next); } } return pkt; out: + list_for_each_entry(opt, &pkt->options, entry) { + while (!list_empty(&opt->list)) { + next = list_entry(opt->list.next, typeof(*next), entry); + list_del(&next->entry); + mempool_free(next); + } + } + dhcpv4_packet_free(pkt); return NULL; } @@ -1199,6 +1245,14 @@ static void load_config() opt = conf_get_opt("dns", "dns2"); if (opt) conf_dns2 = inet_addr(opt); + + opt = conf_get_opt("wins", "wins1"); + if (opt) + conf_wins1 = inet_addr(opt); + + opt = conf_get_opt("wins", "wins2"); + if (opt) + conf_wins2 = inet_addr(opt); } static void init() diff --git a/accel-pppd/ctrl/ipoe/dhcpv4.h b/accel-pppd/ctrl/ipoe/dhcpv4.h index ebb67cfb..3e90cc34 100644 --- a/accel-pppd/ctrl/ipoe/dhcpv4.h +++ b/accel-pppd/ctrl/ipoe/dhcpv4.h @@ -54,6 +54,7 @@ struct dhcpv4_hdr { struct dhcpv4_option { struct list_head entry; + struct list_head list; uint8_t type; uint8_t len; uint8_t *data; |