|
#include <errno.h> |
|
1 |
#include <poll.h> |
#include <poll.h> |
2 |
#include <limits.h> |
#include <limits.h> |
3 |
#include <setjmp.h> |
#include <setjmp.h> |
95 |
dev->hostname, dev->name); |
dev->hostname, dev->name); |
96 |
} |
} |
97 |
|
|
98 |
|
/* |
99 |
|
* Escape shell varialbes in git style: |
100 |
|
* Always start with a single quote ('), then leave all characters |
101 |
|
* except ' and ! unchanged. |
102 |
|
*/ |
103 |
|
static void write_option(FILE* f, const char* name, const char* chr) |
104 |
|
{ |
105 |
|
|
106 |
|
fprintf(f, "%s='", name); |
107 |
|
while (*chr) { |
108 |
|
switch (*chr) { |
109 |
|
case '!': |
110 |
|
case '\'': |
111 |
|
fprintf(f, "'\\%c'", *chr); |
112 |
|
break; |
113 |
|
default: |
114 |
|
fprintf(f, "%c", *chr); |
115 |
|
break; |
116 |
|
} |
117 |
|
++chr; |
118 |
|
} |
119 |
|
fprintf(f, "'\n"); |
120 |
|
} |
121 |
|
|
122 |
static void dump_device_config(struct netdev *dev) |
static void dump_device_config(struct netdev *dev) |
123 |
{ |
{ |
124 |
char fn[40]; |
char fn[40]; |
127 |
snprintf(fn, sizeof(fn), "/tmp/net-%s.conf", dev->name); |
snprintf(fn, sizeof(fn), "/tmp/net-%s.conf", dev->name); |
128 |
f = fopen(fn, "w"); |
f = fopen(fn, "w"); |
129 |
if (f) { |
if (f) { |
130 |
fprintf(f, "DEVICE=%s\n", dev->name); |
write_option(f, "DEVICE", dev->name); |
131 |
fprintf(f, "IPV4ADDR=%s\n", my_inet_ntoa(dev->ip_addr)); |
write_option(f, "IPV4ADDR", |
132 |
fprintf(f, "IPV4BROADCAST=%s\n", |
my_inet_ntoa(dev->ip_addr)); |
133 |
my_inet_ntoa(dev->ip_broadcast)); |
write_option(f, "IPV4BROADCAST", |
134 |
fprintf(f, "IPV4NETMASK=%s\n", my_inet_ntoa(dev->ip_netmask)); |
my_inet_ntoa(dev->ip_broadcast)); |
135 |
fprintf(f, "IPV4GATEWAY=%s\n", my_inet_ntoa(dev->ip_gateway)); |
write_option(f, "IPV4NETMASK", |
136 |
fprintf(f, "IPV4DNS0=%s\n", |
my_inet_ntoa(dev->ip_netmask)); |
137 |
my_inet_ntoa(dev->ip_nameserver[0])); |
write_option(f, "IPV4GATEWAY", |
138 |
fprintf(f, "IPV4DNS1=%s\n", |
my_inet_ntoa(dev->ip_gateway)); |
139 |
my_inet_ntoa(dev->ip_nameserver[1])); |
write_option(f, "IPV4DNS0", |
140 |
fprintf(f, "HOSTNAME=%s\n", dev->hostname); |
my_inet_ntoa(dev->ip_nameserver[0])); |
141 |
fprintf(f, "DNSDOMAIN=%s\n", dev->dnsdomainname); |
write_option(f, "IPV4DNS1", |
142 |
fprintf(f, "NISDOMAIN=%s\n", dev->nisdomainname); |
my_inet_ntoa(dev->ip_nameserver[1])); |
143 |
fprintf(f, "ROOTSERVER=%s\n", my_inet_ntoa(dev->ip_server)); |
write_option(f, "HOSTNAME", dev->hostname); |
144 |
fprintf(f, "ROOTPATH=%s\n", dev->bootpath); |
write_option(f, "DNSDOMAIN", dev->dnsdomainname); |
145 |
fprintf(f, "filename=\"%s\"\n", dev->filename); |
write_option(f, "NISDOMAIN", dev->nisdomainname); |
146 |
|
write_option(f, "ROOTSERVER", |
147 |
|
my_inet_ntoa(dev->ip_server)); |
148 |
|
write_option(f, "ROOTPATH", dev->bootpath); |
149 |
|
write_option(f, "filename", dev->filename); |
150 |
fclose(f); |
fclose(f); |
151 |
} |
} |
152 |
} |
} |
198 |
|
|
199 |
/* |
/* |
200 |
* Returns: |
* Returns: |
201 |
* 0 = Not handled, the packet is still in the queue |
* 0 = Not handled, try again later |
202 |
* 1 = Handled |
* 1 = Handled |
203 |
*/ |
*/ |
204 |
static int process_receive_event(struct state *s, time_t now) |
static int process_receive_event(struct state *s, time_t now) |
206 |
int handled = 1; |
int handled = 1; |
207 |
|
|
208 |
switch (s->state) { |
switch (s->state) { |
209 |
|
case DEVST_ERROR: |
210 |
|
return 0; /* Not handled */ |
211 |
|
case DEVST_COMPLETE: |
212 |
|
return 0; /* Not handled as already configured */ |
213 |
|
|
214 |
case DEVST_BOOTP: |
case DEVST_BOOTP: |
215 |
s->restart_state = DEVST_BOOTP; |
s->restart_state = DEVST_BOOTP; |
216 |
switch (bootp_recv_reply(s->dev)) { |
switch (bootp_recv_reply(s->dev)) { |
217 |
case -1: |
case -1: |
218 |
s->state = DEVST_ERROR; |
s->state = DEVST_ERROR; |
219 |
break; |
break; |
220 |
|
case 0: |
221 |
|
handled = 0; |
222 |
|
break; |
223 |
case 1: |
case 1: |
224 |
s->state = DEVST_COMPLETE; |
s->state = DEVST_COMPLETE; |
225 |
dprintf("\n bootp reply\n"); |
dprintf("\n bootp reply\n"); |
233 |
case -1: |
case -1: |
234 |
s->state = DEVST_ERROR; |
s->state = DEVST_ERROR; |
235 |
break; |
break; |
236 |
|
case 0: |
237 |
|
handled = 0; |
238 |
|
break; |
239 |
case DHCPOFFER: /* Offer received */ |
case DHCPOFFER: /* Offer received */ |
240 |
s->state = DEVST_DHCPREQ; |
s->state = DEVST_DHCPREQ; |
241 |
dhcp_send_request(s->dev); |
dhcp_send_request(s->dev); |
249 |
case -1: /* error */ |
case -1: /* error */ |
250 |
s->state = DEVST_ERROR; |
s->state = DEVST_ERROR; |
251 |
break; |
break; |
252 |
|
case 0: |
253 |
|
handled = 0; |
254 |
|
break; |
255 |
case DHCPACK: /* ACK received */ |
case DHCPACK: /* ACK received */ |
256 |
s->state = DEVST_COMPLETE; |
s->state = DEVST_COMPLETE; |
257 |
break; |
break; |
338 |
|
|
339 |
/* |
/* |
340 |
* Returns: |
* Returns: |
341 |
* 0 = Error, packet not received or discarded |
* 0 = No dhcp/bootp packet was received |
342 |
* 1 = A packet was received and handled |
* 1 = A packet was received and handled |
343 |
*/ |
*/ |
344 |
static int do_pkt_recv(int pkt_fd, time_t now) |
static int do_pkt_recv(int pkt_fd, time_t now) |
345 |
{ |
{ |
346 |
int ifindex, ret; |
int ret; |
347 |
struct state *s; |
struct state *s; |
348 |
|
|
|
ret = packet_peek(&ifindex); |
|
|
if (ret == 0) |
|
|
return ret; |
|
|
|
|
349 |
for (s = slist; s; s = s->next) { |
for (s = slist; s; s = s->next) { |
350 |
if (s->dev->ifindex == ifindex) { |
ret |= process_receive_event(s, now); |
|
ret = process_receive_event(s, now); |
|
|
break; |
|
|
} |
|
351 |
} |
} |
|
|
|
|
if (ret == 0) |
|
|
packet_discard(); |
|
|
|
|
352 |
return ret; |
return ret; |
353 |
} |
} |
354 |
|
|
358 |
struct pollfd fds[NR_FDS]; |
struct pollfd fds[NR_FDS]; |
359 |
struct state *s; |
struct state *s; |
360 |
int pkt_fd; |
int pkt_fd; |
361 |
int nr = 0; |
int nr = 0, rc = 0; |
362 |
struct timeval now, prev; |
struct timeval now, prev; |
363 |
time_t start; |
time_t start; |
364 |
|
|
423 |
now.tv_sec - start >= loop_timeout) { |
now.tv_sec - start >= loop_timeout) { |
424 |
printf("IP-Config: no response after %d " |
printf("IP-Config: no response after %d " |
425 |
"secs - giving up\n", loop_timeout); |
"secs - giving up\n", loop_timeout); |
426 |
|
rc = -1; |
427 |
goto bail; |
goto bail; |
428 |
} |
} |
429 |
|
|
438 |
bail: |
bail: |
439 |
packet_close(); |
packet_close(); |
440 |
|
|
441 |
return 0; |
return rc; |
442 |
} |
} |
443 |
|
|
444 |
static int add_one_dev(struct netdev *dev) |
static int add_one_dev(struct netdev *dev) |
511 |
static int parse_device(struct netdev *dev, const char *ip) |
static int parse_device(struct netdev *dev, const char *ip) |
512 |
{ |
{ |
513 |
char *cp; |
char *cp; |
514 |
int i, opt; |
int opt; |
515 |
int is_ip = 0; |
int is_ip = 0; |
516 |
|
|
517 |
dprintf("IP-Config: parse_device: \"%s\"\n", ip); |
dprintf("IP-Config: parse_device: \"%s\"\n", ip); |
533 |
dev->name = ip; |
dev->name = ip; |
534 |
} |
} |
535 |
} else { |
} else { |
536 |
for (i = opt = 0; ip && *ip; ip = cp, opt++) { |
for (opt = 0; ip && *ip; ip = cp, opt++) { |
537 |
if ((cp = strchr(ip, ':'))) { |
if ((cp = strchr(ip, ':'))) { |
538 |
*cp++ = '\0'; |
*cp++ = '\0'; |
539 |
} |
} |
564 |
case 4: |
case 4: |
565 |
strncpy(dev->hostname, ip, SYS_NMLN - 1); |
strncpy(dev->hostname, ip, SYS_NMLN - 1); |
566 |
dev->hostname[SYS_NMLN - 1] = '\0'; |
dev->hostname[SYS_NMLN - 1] = '\0'; |
567 |
memcpy(dev->reqhostname, dev->hostname, |
memcpy(dev->reqhostname, dev->hostname, |
568 |
SYS_NMLN); |
SYS_NMLN); |
569 |
break; |
break; |
570 |
case 5: |
case 5: |
752 |
{ |
{ |
753 |
struct netdev *dev; |
struct netdev *dev; |
754 |
int c, port; |
int c, port; |
755 |
int err; |
int err = 0; |
756 |
|
|
757 |
/* If progname is set we're invoked from another program */ |
/* If progname is set we're invoked from another program */ |
758 |
if (!progname) { |
if (!progname) { |
830 |
"dest to %d\n", |
"dest to %d\n", |
831 |
cfg_local_port, cfg_remote_port); |
cfg_local_port, cfg_remote_port); |
832 |
} |
} |
833 |
loop(); |
err = loop(); |
834 |
} |
} |
835 |
|
|
836 |
return 0; |
return err; |
837 |
} |
} |