-
Notifications
You must be signed in to change notification settings - Fork 1
/
fixup_net_config.c
286 lines (247 loc) · 6.83 KB
/
fixup_net_config.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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <rtems.h>
#include <rtems/rtems_bsdnet.h>
#include <rtems/rtems_mii_ioctl.h>
#include <assert.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include "libnetboot.h"
/* there is no public Workspace_Free() variant :-( */
#include <rtems/score/wkspace.h>
/* We'll store here what the application put into its
* network configuration table.
*/
static void (*the_apps_bootp)(void)=0;
static void my_bootp_intercept(void);
static void fillin_srvrandfile(void);
#define bootp_file rtems_bsdnet_bootp_boot_file_name
#define bootp_cmdline rtems_bsdnet_bootp_cmdline
#define bootp_srvr rtems_bsdnet_bootp_server_address
#define net_config rtems_bsdnet_config
extern int rtems_bsdnet_loopattach(struct rtems_bsdnet_ifconfig*, int);
#define loopattach rtems_bsdnet_loopattach
/* parameter table for network setup - separate file because
* copied from the bootloader
*/
#include "nvram.c"
#ifndef HAVE_BSP_COMMANDLINE_STRING
/* netboot may override stuff in the commandline
* but we need to provide specially tagged space (which is intended to be
* overwritten by netboot):
*/
#ifndef BSP_CMDLINEBUFSZ
#define BSP_CMDLINEBUFSZ 1024
#endif
static char cmdlinebuf[BSP_CMDLINEBUFSZ] = {
COMMANDLINEBUF_TAG,
((BSP_CMDLINEBUFSZ>>12)&0xf) + '0',
((BSP_CMDLINEBUFSZ>> 8)&0xf) + '0',
((BSP_CMDLINEBUFSZ>> 4)&0xf) + '0',
((BSP_CMDLINEBUFSZ>> 0)&0xf) + '0',
0,
};
char *BSP_commandline_string = cmdlinebuf;
#endif
static char *boot_my_media = 0;
static char do_bootp()
{
return boot_use_bootp ? toupper((unsigned char)*boot_use_bootp) : 'Y';
}
static void
fillin_srvrandfile(void)
{
/* OK - now let's see what we have */
if (boot_srvname) {
/* Seems we have a different file server */
if (inet_pton(AF_INET,
boot_srvname,
&bootp_srvr)) {
}
}
/* Ha - they manually changed the file name and the parameters */
bootp_file = boot_filename;
/* (dont bother freeing the old one - we don't really know if its malloced */
boot_filename = 0;
/* comments for boot_filename apply here as well */
bootp_cmdline = boot_parms;
}
/* Scan the list of interfaces for the first non-loopback
* one. (Same algorithm 'bootp' uses -- except we can't check
* the flags because a) interfaces are not up yet (when called
* from the 'fixup' routine or b) we don't have access to the
* 'kernel' internals without even worse hacking...)
*/
static struct rtems_bsdnet_ifconfig *
find_first_real_if()
{
struct rtems_bsdnet_ifconfig *ifc;
/* interfaces are not up yet -- we can't check their flags */
for (ifc=net_config.ifconfig;
ifc && loopattach==ifc->attach;
ifc=ifc->next) {
/* should probably make sure it's not a point-to-point
* IF either
*/
}
return ifc;
}
/* if the bootloader loaded a different file
* than what the BOOTP/DHCP server says we have
* then we want to forge the respective system
* variables.
*/
static void
my_bootp_intercept(void)
{
int media;
/* Interfaces are attached; now see if we should set the media
* Note that we treat the case of an empty media string and
* 'auto' differently. In the former case, we simply leave the
* IF alone, otherwise we enforce autoconfig.
*/
if ( boot_my_media && *boot_my_media ) {
/* Only do something if the string is not empty */
media = rtems_str2ifmedia(boot_my_media, 0/* only 1 phy supported here */);
if ( !media ) {
fprintf(stderr,"Unable to configure IF media - invalid parameter '%s'\n",boot_my_media);
} else {
/* network port has already been selected and the IF name fixed */
struct rtems_bsdnet_ifconfig *ifc;
ifc = find_first_real_if();
if ( !ifc ) {
fprintf(stderr,"Unable to set IF media - no interface found\n");
} else {
if ( rtems_bsdnet_ifconfig(ifc->name, SIOCSIFMEDIA, &media )) {
fprintf(stderr,
"Setting IF media on %s (SIOCSIFMEDIA) failed: %s\n",
ifc->name, strerror(errno));
}
}
}
}
/* now check if we should do real bootp */
if ( 'N' != do_bootp() ) {
/* Do bootp first */
if (the_apps_bootp) {
the_apps_bootp();
} else {
rtems_bsdnet_do_bootp();
}
}
if ( 'Y' != do_bootp() ) {
/* override the server/filename parameters */
fillin_srvrandfile();
}
}
static int
putparm(char *str)
{
Parm p;
/* save special bootloader strings to our private environment
* and pass on the others
*/
for (p=parmList; p->name; p++) {
if (!p->pval) {
continue;
}
if (0 == strncmp(str,p->name,strlen(p->name))) {
/* found this one; since 'name' contains a '=' strchr will succeed */
char *s=strchr(str,'=')+1;
/* p->pval might point into the
* network configuration which is invalid
* if we have no networking
*/
{
/* recent gcc says &net_config is always true
* but it could in fact be supplied by the linker
* which means it could be 0. Hence we use a dummy
* variable which seems to silence gcc-4.2.2 for now
*/
void *tester = &net_config;
if (tester) {
*p->pval=malloc(strlen(s)+1);
strcpy(*p->pval,s);
}
}
return 0;
}
}
return -1;
}
void
nvramFixupBsdnetConfig(int readNvram, char *argline)
{
Parm p;
struct rtems_bsdnet_ifconfig *ifc;
/* now hack into the network configuration... */
/* extract_boot_params() modifies the commandline string (part of the fixup) */
if ( readNvram ) {
NetConfigCtxtRec ctx;
lock();
netConfigCtxtInitialize(&ctx,stdout,0);
readNVRAM(&ctx);
netConfigCtxtFinalize(&ctx);
unlock();
}
#ifndef HAVE_BSP_COMMANDLINE_STRING
if ( !argline )
#ifdef HAVE_BSP_CMDLINE
argline = bsp_cmdline();
#else
argline = cmdlinebuf;
#endif
#endif
if ( argline )
cmdlinePairExtract(argline, putparm, 1);
if ( boot_my_if ) {
if ( (boot_my_media = strchr(boot_my_if,':')) ) {
*boot_my_media++ = 0;
if ( 0 == *boot_my_if )
boot_my_if = 0;
} else {
boot_my_media = boot_my_if;
boot_my_if = 0;
}
#ifndef BSP_HAS_MULTIPLE_NETIFS
/* just drop the interface name */
boot_my_if = 0;
#endif
}
ifc = find_first_real_if();
assert(ifc && "NO INTERFACE CONFIGURATION STRUCTURE FOUND");
if ( boot_my_if )
ifc->name = boot_my_if;
if ( 'N' == do_bootp() ) {
/* no bootp */
/* get pointers to the first interface's configuration */
ifc->ip_address = boot_my_ip;
boot_my_ip=0;
ifc->ip_netmask = boot_my_netmask;
boot_my_netmask = 0;
} else {
the_apps_bootp=net_config.bootp;
/* release the strings that will be set up by
* bootp - bootpc relies on them being NULL
*/
for (p=parmList; p->name; p++) {
if (!p->pval) continue;
if (p->flags & FLAG_CLRBP) {
free(*p->pval); *p->pval=0;
}
}
}
/* Always intercept; this gives us a chance do to things
* after the interfaces are attached
*/
net_config.bootp=my_bootp_intercept;
}