diff options
Diffstat (limited to 'slirp/src/dhcpv6.c')
m--------- | slirp | 0 | ||||
-rw-r--r-- | slirp/src/dhcpv6.c | 224 |
2 files changed, 0 insertions, 224 deletions
diff --git a/slirp b/slirp new file mode 160000 +Subproject 59a1b1f165458c2acb7ff0525b543945f741622 diff --git a/slirp/src/dhcpv6.c b/slirp/src/dhcpv6.c deleted file mode 100644 index 3c8f420912..0000000000 --- a/slirp/src/dhcpv6.c +++ /dev/null @@ -1,224 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * 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. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#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]); - } -} |