aboutsummaryrefslogtreecommitdiff
path: root/slirp/dhcpv6.c
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@redhat.com>2019-02-12 17:25:21 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2019-03-07 12:46:31 +0100
commitc2d63650d962612cfa1b21302782d4cd12142c74 (patch)
tree13f97c3ecbf6a6588f579e9f7c2ab9cb5f3ce5ec /slirp/dhcpv6.c
parent5a4af0d4ee6084fdfde0125c45181fa0e6f48a17 (diff)
slirp: move sources to src/ subdirectory
Prepare for making slirp/ a standalone project. Remove some useless includes while at it. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <20190212162524.31504-5-marcandre.lureau@redhat.com> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Diffstat (limited to 'slirp/dhcpv6.c')
-rw-r--r--slirp/dhcpv6.c206
1 files changed, 0 insertions, 206 deletions
diff --git a/slirp/dhcpv6.c b/slirp/dhcpv6.c
deleted file mode 100644
index e655c7d5b1..0000000000
--- a/slirp/dhcpv6.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * SLIRP stateless DHCPv6
- *
- * We only support stateless DHCPv6, e.g. for network booting.
- * See RFC 3315, RFC 3736, RFC 3646 and RFC 5970 for details.
- *
- * Copyright 2016 Thomas Huth, Red Hat Inc.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "slirp.h"
-#include "dhcpv6.h"
-
-/* DHCPv6 message types */
-#define MSGTYPE_REPLY 7
-#define MSGTYPE_INFO_REQUEST 11
-
-/* DHCPv6 option types */
-#define OPTION_CLIENTID 1
-#define OPTION_IAADDR 5
-#define OPTION_ORO 6
-#define OPTION_DNS_SERVERS 23
-#define OPTION_BOOTFILE_URL 59
-
-struct requested_infos {
- uint8_t *client_id;
- int client_id_len;
- bool want_dns;
- bool want_boot_url;
-};
-
-/**
- * Analyze the info request message sent by the client to see what data it
- * provided and what it wants to have. The information is gathered in the
- * "requested_infos" struct. Note that client_id (if provided) points into
- * the odata region, thus the caller must keep odata valid as long as it
- * needs to access the requested_infos struct.
- */
-static int dhcpv6_parse_info_request(Slirp *slirp, uint8_t *odata, int olen,
- struct requested_infos *ri)
-{
- int i, req_opt;
-
- while (olen > 4) {
- /* Parse one option */
- int option = odata[0] << 8 | odata[1];
- int len = odata[2] << 8 | odata[3];
-
- if (len + 4 > olen) {
- slirp->cb->guest_error("Guest sent bad DHCPv6 packet!", slirp->opaque);
- return -E2BIG;
- }
-
- switch (option) {
- case OPTION_IAADDR:
- /* According to RFC3315, we must discard requests with IA option */
- return -EINVAL;
- case OPTION_CLIENTID:
- if (len > 256) {
- /* Avoid very long IDs which could cause problems later */
- return -E2BIG;
- }
- ri->client_id = odata + 4;
- ri->client_id_len = len;
- break;
- case OPTION_ORO: /* Option request option */
- if (len & 1) {
- return -EINVAL;
- }
- /* Check which options the client wants to have */
- for (i = 0; i < len; i += 2) {
- req_opt = odata[4 + i] << 8 | odata[4 + i + 1];
- switch (req_opt) {
- case OPTION_DNS_SERVERS:
- ri->want_dns = true;
- break;
- case OPTION_BOOTFILE_URL:
- ri->want_boot_url = true;
- break;
- default:
- DEBUG_MISC("dhcpv6: Unsupported option request %d",
- req_opt);
- }
- }
- break;
- default:
- DEBUG_MISC("dhcpv6 info req: Unsupported option %d, len=%d",
- option, len);
- }
-
- odata += len + 4;
- olen -= len + 4;
- }
-
- return 0;
-}
-
-
-/**
- * Handle information request messages
- */
-static void dhcpv6_info_request(Slirp *slirp, struct sockaddr_in6 *srcsas,
- uint32_t xid, uint8_t *odata, int olen)
-{
- struct requested_infos ri = { NULL };
- struct sockaddr_in6 sa6, da6;
- struct mbuf *m;
- uint8_t *resp;
-
- if (dhcpv6_parse_info_request(slirp, odata, olen, &ri) < 0) {
- return;
- }
-
- m = m_get(slirp);
- if (!m) {
- return;
- }
- memset(m->m_data, 0, m->m_size);
- m->m_data += IF_MAXLINKHDR;
- resp = (uint8_t *)m->m_data + sizeof(struct ip6) + sizeof(struct udphdr);
-
- /* Fill in response */
- *resp++ = MSGTYPE_REPLY;
- *resp++ = (uint8_t)(xid >> 16);
- *resp++ = (uint8_t)(xid >> 8);
- *resp++ = (uint8_t)xid;
-
- if (ri.client_id) {
- *resp++ = OPTION_CLIENTID >> 8; /* option-code high byte */
- *resp++ = OPTION_CLIENTID; /* option-code low byte */
- *resp++ = ri.client_id_len >> 8; /* option-len high byte */
- *resp++ = ri.client_id_len; /* option-len low byte */
- memcpy(resp, ri.client_id, ri.client_id_len);
- resp += ri.client_id_len;
- }
- if (ri.want_dns) {
- *resp++ = OPTION_DNS_SERVERS >> 8; /* option-code high byte */
- *resp++ = OPTION_DNS_SERVERS; /* option-code low byte */
- *resp++ = 0; /* option-len high byte */
- *resp++ = 16; /* option-len low byte */
- memcpy(resp, &slirp->vnameserver_addr6, 16);
- resp += 16;
- }
- if (ri.want_boot_url) {
- uint8_t *sa = slirp->vhost_addr6.s6_addr;
- int slen, smaxlen;
-
- *resp++ = OPTION_BOOTFILE_URL >> 8; /* option-code high byte */
- *resp++ = OPTION_BOOTFILE_URL; /* option-code low byte */
- smaxlen = (uint8_t *)m->m_data + IF_MTU - (resp + 2);
- slen = snprintf((char *)resp + 2, smaxlen,
- "tftp://[%02x%02x:%02x%02x:%02x%02x:%02x%02x:"
- "%02x%02x:%02x%02x:%02x%02x:%02x%02x]/%s",
- sa[0], sa[1], sa[2], sa[3], sa[4], sa[5], sa[6], sa[7],
- sa[8], sa[9], sa[10], sa[11], sa[12], sa[13], sa[14],
- sa[15], slirp->bootp_filename);
- slen = MIN(slen, smaxlen);
- *resp++ = slen >> 8; /* option-len high byte */
- *resp++ = slen; /* option-len low byte */
- resp += slen;
- }
-
- sa6.sin6_addr = slirp->vhost_addr6;
- sa6.sin6_port = DHCPV6_SERVER_PORT;
- da6.sin6_addr = srcsas->sin6_addr;
- da6.sin6_port = srcsas->sin6_port;
- m->m_data += sizeof(struct ip6) + sizeof(struct udphdr);
- m->m_len = resp - (uint8_t *)m->m_data;
- udp6_output(NULL, m, &sa6, &da6);
-}
-
-/**
- * Handle DHCPv6 messages sent by the client
- */
-void dhcpv6_input(struct sockaddr_in6 *srcsas, struct mbuf *m)
-{
- uint8_t *data = (uint8_t *)m->m_data + sizeof(struct udphdr);
- int data_len = m->m_len - sizeof(struct udphdr);
- uint32_t xid;
-
- if (data_len < 4) {
- return;
- }
-
- xid = ntohl(*(uint32_t *)data) & 0xffffff;
-
- switch (data[0]) {
- case MSGTYPE_INFO_REQUEST:
- dhcpv6_info_request(m->slirp, srcsas, xid, &data[4], data_len - 4);
- break;
- default:
- DEBUG_MISC("dhcpv6_input: Unsupported message type 0x%x", data[0]);
- }
-}