-
Notifications
You must be signed in to change notification settings - Fork 193
/
fs.c
152 lines (130 loc) · 4.71 KB
/
fs.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/* SPDX-License-Identifier: LGPL-3.0-or-later */
/* Copyright (C) 2022 Intel Corporation
* Mariusz Zaborski <[email protected]>
*/
/*
* This file contains the implementation of `etc` FS.
* LibOS assumes that contents of all data obtained from host were already sanitized.
*/
#include "libos_checkpoint.h"
#include "libos_fs.h"
#include "libos_fs_pseudo.h"
#define OPTION_INET6 "options inet6\n"
#define OPTION_ROTATE "options rotate\n"
static int put_string(char** buf, size_t* bufsize, const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
int ret = vsnprintf(*buf, *bufsize, fmt, ap);
va_end(ap);
if (ret < 0)
return ret;
assert(*bufsize > (size_t)ret);
*bufsize -= ret;
*buf += ret;
return 0;
}
static int provide_etc_resolv_conf(struct libos_dentry* dent, char** out_data, size_t* out_size) {
__UNUSED(dent);
size_t size = 0;
/* Estimate the size of buffer: */
/* nameservers - lets assume all entries will be IPv6 plus a new line */
size += g_pal_public_state->dns_host.nsaddr_list_count * (strlen("nameserver ") + 40 + 1);
/* search - lets assume maximum length of entries, plus a new line and white spaces */
size += strlen("search") + 1;
size += g_pal_public_state->dns_host.dnsrch_count * (PAL_HOSTNAME_MAX + 1);
/* and lets add some space for each option */
size += (g_pal_public_state->dns_host.inet6 ? strlen(OPTION_INET6) : 0) +
(g_pal_public_state->dns_host.rotate ? strlen(OPTION_ROTATE) : 0);
/* snprintf adds the terminating character */
size += 1;
char* data = malloc(size);
if (!data)
return -ENOMEM;
/* Generate data: */
char* ptr = data;
int ret = 0;
for (size_t i = 0; i < g_pal_public_state->dns_host.nsaddr_list_count; i++) {
if (!g_pal_public_state->dns_host.nsaddr_list[i].is_ipv6) {
uint32_t addr = g_pal_public_state->dns_host.nsaddr_list[i].ipv4;
ret = put_string(&ptr, &size, "nameserver %u.%u.%u.%u\n",
(addr & 0xFF000000) >> 24, (addr & 0x00FF0000) >> 16,
(addr & 0x0000FF00) >> 8, (addr & 0x000000FF));
} else {
uint16_t* addrv6 = g_pal_public_state->dns_host.nsaddr_list[i].ipv6;
ret = put_string(&ptr, &size, "nameserver %x:%x:%x:%x:%x:%x:%x:%x\n",
addrv6[0], addrv6[1], addrv6[2], addrv6[3], addrv6[4], addrv6[5],
addrv6[6], addrv6[7]);
}
if (ret < 0)
goto out;
}
if (g_pal_public_state->dns_host.dnsrch_count > 0) {
ret = put_string(&ptr, &size, "search");
if (ret < 0)
goto out;
for (size_t i = 0; i < g_pal_public_state->dns_host.dnsrch_count; i++) {
ret = put_string(&ptr, &size, " %s", g_pal_public_state->dns_host.dnsrch[i]);
if (ret < 0)
goto out;
}
ret = put_string(&ptr, &size, "\n");
if (ret < 0)
goto out;
}
if (g_pal_public_state->dns_host.inet6) {
ret = put_string(&ptr, &size, OPTION_INET6);
if (ret < 0)
goto out;
}
if (g_pal_public_state->dns_host.rotate) {
ret = put_string(&ptr, &size, OPTION_ROTATE);
if (ret < 0)
goto out;
}
/* Use the string (without null terminator) as file data */
size_t finalsize = strlen(data);
char* finalbuf = malloc(finalsize);
if (!finalbuf) {
ret = -ENOMEM;
goto out;
}
assert(finalsize <= size);
memcpy(finalbuf, data, finalsize);
*out_data = finalbuf;
*out_size = finalsize;
ret = 0;
out:
free(data);
return ret;
}
int init_etcfs(void) {
pseudo_add_str(NULL, "emulate-etc-resolv-conf", &provide_etc_resolv_conf);
return 0;
}
int mount_etcfs(void) {
if (!g_pal_public_state->emulate_etc_files)
return 0;
return mount_fs(&(struct libos_mount_params){
.type = "pseudo",
.path = "/etc/resolv.conf",
.uri = "emulate-etc-resolv-conf",
});
}
BEGIN_CP_FUNC(etc_info) {
__UNUSED(size);
__UNUSED(obj);
__UNUSED(objp);
/* Propagate DNS configuration */
size_t off = ADD_CP_OFFSET(sizeof(g_pal_public_state->dns_host));
struct dns_host* new_dns_host = (struct dns_host*)(base + off);
memcpy(new_dns_host, &g_pal_public_state->dns_host, sizeof(g_pal_public_state->dns_host));
ADD_CP_FUNC_ENTRY(off);
}
END_CP_FUNC(etc_info)
BEGIN_RS_FUNC(etc_info) {
__UNUSED(offset);
__UNUSED(rebase);
const struct dns_host* dns_host = (const struct dns_host*)(base + GET_CP_FUNC_ENTRY());
memcpy(&g_pal_public_state->dns_host, dns_host, sizeof(g_pal_public_state->dns_host));
}
END_RS_FUNC(etc_info)