11
#include <arpa/inet.h>
12
#include <sys/types.h>
16
#include <unistd.h> /* for getopts */
18
#include <net/if_arp.h>
22
#include "bootp_packet.h"
23
#include "bootp_proto.h"
24
#include "dhcp_proto.h"
27
static const char sysfs_class_net[] = "/sys/class/net";
28
static const char *progname;
29
static char do_not_config;
30
static unsigned int default_caps = CAP_DHCP | CAP_BOOTP | CAP_RARP;
31
static int loop_timeout = -1;
32
static int configured;
44
static inline const char *my_inet_ntoa(__u32 addr)
53
static void print_device_config(struct netdev *dev)
55
printf("IP-Config: %s complete (from %s):\n", dev->name,
56
my_inet_ntoa(dev->serverid ? dev->serverid : dev->ip_server));
57
printf(" address: %-16s ", my_inet_ntoa(dev->ip_addr));
58
printf("broadcast: %-16s ", my_inet_ntoa(dev->ip_broadcast));
59
printf("netmask: %-16s\n", my_inet_ntoa(dev->ip_netmask));
60
printf(" gateway: %-16s ", my_inet_ntoa(dev->ip_gateway));
61
printf("dns0 : %-16s ", my_inet_ntoa(dev->ip_nameserver[0]));
62
printf("dns1 : %-16s\n", my_inet_ntoa(dev->ip_nameserver[1]));
64
printf(" host : %-64s\n", dev->hostname);
65
if (dev->dnsdomainname[0])
66
printf(" domain : %-64s\n", dev->dnsdomainname);
67
if (dev->nisdomainname[0])
68
printf(" nisdomain: %-64s\n", dev->nisdomainname);
69
printf(" rootserver: %s ", my_inet_ntoa(dev->ip_server));
70
printf("rootpath: %s\n", dev->bootpath);
73
static void configure_device(struct netdev *dev)
78
if (netdev_setmtu(dev))
79
printf("IP-Config: failed to set MTU on %s to %u\n",
82
if (netdev_setaddress(dev))
83
printf("IP-Config: failed to set addresses on %s\n", dev->name);
84
if (netdev_setdefaultroute(dev))
85
printf("IP-Config: failed to set default route on %s\n", dev->name);
88
static void dump_device_config(struct netdev *dev)
93
snprintf(fn, sizeof(fn), "/tmp/net-%s.conf", dev->name);
96
fprintf(f, "DEVICE=%s\n", dev->name);
97
fprintf(f, "IPV4ADDR=%s\n", my_inet_ntoa(dev->ip_addr));
98
fprintf(f, "IPV4BROADCAST=%s\n", my_inet_ntoa(dev->ip_broadcast));
99
fprintf(f, "IPV4NETMASK=%s\n", my_inet_ntoa(dev->ip_netmask));
100
fprintf(f, "IPV4GATEWAY=%s\n", my_inet_ntoa(dev->ip_gateway));
101
fprintf(f, "IPV4DNS0=%s\n", my_inet_ntoa(dev->ip_nameserver[0]));
102
fprintf(f, "IPV4DNS1=%s\n", my_inet_ntoa(dev->ip_nameserver[1]));
103
fprintf(f, "HOSTNAME=%s\n", dev->hostname);
104
fprintf(f, "DNSDOMAIN=%s\n", dev->dnsdomainname);
105
fprintf(f, "NISDOMAIN=%s\n", dev->nisdomainname);
106
fprintf(f, "ROOTSERVER=%s\n", my_inet_ntoa(dev->ip_server));
107
fprintf(f, "ROOTPATH=%s\n", dev->bootpath);
112
static __u32 inet_class_netmask(__u32 ip)
116
return htonl(IN_CLASSA_NET);
118
return htonl(IN_CLASSB_NET);
120
return htonl(IN_CLASSC_NET);
124
static void postprocess_device(struct netdev *dev)
126
if (dev->ip_netmask == INADDR_ANY) {
127
dev->ip_netmask = inet_class_netmask(dev->ip_addr);
128
printf("IP-Config: %s guessed netmask %s\n",
129
dev->name, my_inet_ntoa(dev->ip_netmask));
131
if (dev->ip_broadcast == INADDR_ANY) {
132
dev->ip_broadcast = (dev->ip_addr & dev->ip_netmask) | ~dev->ip_netmask;
133
printf("IP-Config: %s guessed broadcast address %s\n",
134
dev->name, my_inet_ntoa(dev->ip_broadcast));
136
if (dev->ip_nameserver[0] == INADDR_ANY) {
137
dev->ip_nameserver[0] = dev->ip_server;
138
printf("IP-Config: %s guessed nameserver address %s\n",
139
dev->name, my_inet_ntoa(dev->ip_nameserver[0]));
143
static void complete_device(struct netdev *dev)
145
postprocess_device(dev);
146
configure_device(dev);
147
dump_device_config(dev);
148
print_device_config(dev);
156
static int process_receive_event(struct state *s, time_t now)
162
s->restart_state = DEVST_BOOTP;
163
switch (bootp_recv_reply(s->dev)) {
165
s->state = DEVST_ERROR;
168
s->state = DEVST_COMPLETE;
169
DEBUG(("\n bootp reply\n"));
175
s->restart_state = DEVST_DHCPDISC;
176
switch (dhcp_recv_offer(s->dev)) {
178
s->state = DEVST_ERROR;
180
case 1: /* Offer received */
181
s->state = DEVST_DHCPREQ;
182
dhcp_send_request(s->dev);
188
s->restart_state = DEVST_DHCPDISC;
189
switch (dhcp_recv_ack(s->dev)) {
191
s->state = DEVST_ERROR;
193
case 1: /* ACK received */
194
s->state = DEVST_COMPLETE;
196
case 2: /* NAK received */
197
s->state = DEVST_DHCPDISC;
205
complete_device(s->dev);
209
/* error occurred, try again in 10 seconds */
210
s->expire = now + 10;
220
static void process_timeout_event(struct state *s, time_t now)
225
* Is the link up? If not, try again in 1 second.
227
if (!netdev_running(s->dev)) {
229
s->state = s->restart_state;
234
* If we had an error, restore a sane state to
237
if (s->state == DEVST_ERROR)
238
s->state = s->restart_state;
241
* Now send a packet depending on our state.
245
ret = bootp_send_request(s->dev);
246
s->restart_state = DEVST_BOOTP;
250
ret = dhcp_send_discover(s->dev);
251
s->restart_state = DEVST_DHCPDISC;
255
ret = dhcp_send_request(s->dev);
256
s->restart_state = DEVST_DHCPDISC;
261
s->state = DEVST_ERROR;
262
s->expire = now + 10;
264
s->expire = now + s->retry_period;
266
s->retry_period *= 2;
267
if (s->retry_period > 60)
268
s->retry_period = 60;
272
static struct state *slist;
273
struct netdev *ifaces;
275
static int do_pkt_recv(int pkt_fd, time_t now)
280
ret = packet_peek(&ifindex);
284
for (s = slist; s; s = s->next) {
285
if (s->dev->ifindex == ifindex) {
286
ret |= process_receive_event(s, now);
295
static int loop(void)
298
struct pollfd fds[NR_FDS];
302
struct timeval now, prev;
305
pkt_fd = packet_open();
307
perror("packet_open");
312
fds[0].events = POLLRDNORM;
314
gettimeofday(&now, NULL);
322
for (s = slist; s; s = s->next) {
323
if (s->state == DEVST_COMPLETE)
328
if (s->expire - now.tv_sec <= 0)
329
process_timeout_event(s, now.tv_sec);
331
if (timeout > s->expire - now.tv_sec)
332
timeout = s->expire - now.tv_sec;
338
timeout_ms = timeout * 1000;
340
for (x = 0; x < 2; x++) {
346
nr = poll(fds, NR_FDS, timeout_ms);
348
gettimeofday(&now, NULL);
350
if ((fds[0].revents & POLLRDNORM)) {
351
nr = do_pkt_recv(pkt_fd, now.tv_sec);
358
if (loop_timeout >= 0 &&
359
now.tv_sec - start >= loop_timeout) {
360
printf("IP-Config: no response after %d "
361
"secs - giving up\n", loop_timeout);
365
delta_ms = (now.tv_sec - prev.tv_sec) * 1000;
366
delta_ms += (now.tv_usec - prev.tv_usec) / 1000;
368
DEBUG(("Delta: %d ms\n", delta_ms));
370
timeout_ms -= delta_ms;
379
static int add_one_dev(struct netdev *dev)
383
state = malloc(sizeof(struct state));
388
state->expire = time(NULL);
389
state->retry_period = 1;
392
* Select the state that we start from.
394
if (dev->caps & CAP_DHCP && dev->ip_addr == INADDR_ANY) {
395
state->restart_state = state->state = DEVST_DHCPDISC;
396
} else if (dev->caps & CAP_DHCP) {
397
state->restart_state = state->state = DEVST_DHCPREQ;
398
} else if (dev->caps & CAP_BOOTP) {
399
state->restart_state = state->state = DEVST_BOOTP;
408
static void parse_addr(__u32 *addr, const char *ip)
411
if (inet_aton(ip, &in) == 0) {
412
fprintf(stderr, "%s: can't parse IP address '%s'\n",
419
static unsigned int parse_proto(const char *ip)
421
unsigned int caps = 0;
423
if (*ip == '\0' || strcmp(ip, "on") == 0 || strcmp(ip, "any") == 0)
424
caps = CAP_BOOTP | CAP_DHCP | CAP_RARP;
425
else if (strcmp(ip, "both") == 0)
426
caps = CAP_BOOTP | CAP_RARP;
427
else if (strcmp(ip, "dhcp") == 0)
428
caps = CAP_BOOTP | CAP_DHCP;
429
else if (strcmp(ip, "bootp") == 0)
431
else if (strcmp(ip, "rarp") == 0)
433
else if (strcmp(ip, "none") == 0 || strcmp(ip, "static") == 0 || strcmp(ip, "off") == 0)
436
fprintf(stderr, "%s: invalid protocol '%s'\n",
444
static int add_all_devices(struct netdev *template);
446
static int parse_device(struct netdev *dev, const char *ip)
451
if (strncmp(ip, "ip=", 3) == 0) {
454
else if (strncmp(ip, "nfsaddrs=", 9) == 0) {
458
if (strchr(ip, ':') == NULL) {
463
for (i = opt = 0; ip && *ip; ip = cp, opt++) {
464
if ((cp = strchr(ip, ':'))) {
468
fprintf(stderr, "%s: too many options for %s\n",
469
progname, dev->name);
475
DEBUG(("IP-Config: opt #%d: '%s'\n", opt, ip));
478
parse_addr(&dev->ip_addr, ip);
482
parse_addr(&dev->ip_server, ip);
485
parse_addr(&dev->ip_gateway, ip);
488
parse_addr(&dev->ip_netmask, ip);
491
strncpy(dev->hostname, ip, SYS_NMLN - 1);
492
dev->hostname[SYS_NMLN - 1] = '\0';
498
dev->caps = parse_proto(ip);
503
if (dev->name == NULL ||
504
dev->name[0] == '\0' ||
505
strcmp(dev->name, "all") == 0) {
506
add_all_devices(dev);
512
static void bringup_device(struct netdev *dev)
514
if (netdev_up(dev) == 0) {
518
complete_device(dev);
523
static void bringup_one_dev(struct netdev *template, struct netdev *dev)
525
if (template->ip_addr != INADDR_NONE)
526
dev->ip_addr = template->ip_addr;
527
if (template->ip_server != INADDR_NONE)
528
dev->ip_server = template->ip_server;
529
if (template->ip_gateway != INADDR_NONE)
530
dev->ip_gateway = template->ip_gateway;
531
if (template->ip_netmask != INADDR_NONE)
532
dev->ip_netmask = template->ip_netmask;
533
if (template->ip_nameserver[0] != INADDR_NONE)
534
dev->ip_nameserver[0] = template->ip_nameserver[0];
535
if (template->ip_nameserver[1] != INADDR_NONE)
536
dev->ip_nameserver[1] = template->ip_nameserver[1];
537
if (template->hostname[0] != '\0')
538
strcpy(dev->hostname, template->hostname);
539
dev->caps &= template->caps;
544
static struct netdev *add_device(const char *info)
549
dev = malloc(sizeof(struct netdev));
551
fprintf(stderr, "%s: out of memory\n", progname);
555
memset(dev, 0, sizeof(struct netdev));
556
dev->caps = default_caps;
558
if (parse_device(dev, info) == 0)
561
if (netdev_init_if(dev) == -1)
564
if (bootp_init_if(dev) == -1)
567
printf("IP-Config: %s hardware address", dev->name);
568
for (i = 0; i < dev->hwlen; i++)
569
printf("%c%02x", i == 0 ? ' ' : ':', dev->hwaddr[i]);
570
printf(" mtu %d%s%s\n", dev->mtu,
571
dev->caps & CAP_DHCP ? " DHCP" :
572
dev->caps & CAP_BOOTP ? " BOOTP" : "",
573
dev->caps & CAP_RARP ? " RARP" : "");
580
static int add_all_devices(struct netdev *template)
585
char t[PATH_MAX], p[255];
589
d = opendir(sysfs_class_net);
593
while((de = readdir(d)) != NULL ) {
594
/* This excludes devices beginning with dots or "dummy", as well as . or .. */
595
if ( de->d_name[0] == '.' || !strcmp(de->d_name, "..") )
597
i = snprintf(t, PATH_MAX-1, "%s/%s/flags", sysfs_class_net, de->d_name);
598
if (i < 0 || i >= PATH_MAX-1)
601
fd = open(t, O_RDONLY);
606
i = read(fd, &p, sizeof(p) - 1);
613
flags = strtoul(p, NULL, 0);
614
/* Heuristic for if this is a reasonable boot interface.
616
logic the in-kernel ipconfig uses... */
617
if ( !(flags & IFF_LOOPBACK) &&
618
(flags & (IFF_BROADCAST|IFF_POINTOPOINT)) )
620
if ( !(dev = add_device(de->d_name)) )
622
bringup_one_dev(template, dev);
629
static int check_autoconfig(void)
631
int ndev = 0, nauto = 0;
634
for (s = slist; s; s = s->next) {
641
if (configured == 0) {
642
fprintf(stderr, "%s: no devices to configure\n",
651
int main(int argc, char *argv[])
652
__attribute__ ((weak, alias ("ipconfig_main")));
654
int ipconfig_main(int argc, char *argv[])
662
gettimeofday(&now, NULL);
663
srand48(now.tv_usec ^ (now.tv_sec << 24));
666
c = getopt(argc, argv, "c:d:np:t:");
672
default_caps = parse_proto(optarg);
676
if (port <= 0 || port > USHRT_MAX) {
678
"%s: invalid port number %d\n",
682
cfg_local_port = port;
683
cfg_remote_port = cfg_local_port - 1;
686
loop_timeout = atoi(optarg);
687
if (loop_timeout < 0) {
689
"%s: invalid timeout %d\n",
690
progname, loop_timeout);
698
dev = add_device(optarg);
703
fprintf(stderr, "%s: invalid option -%c\n",
709
for (c = optind; c < argc; c++) {
710
dev = add_device(argv[c]);
715
if (check_autoconfig()) {
716
if (cfg_local_port != LOCAL_PORT) {
717
printf("IP-Config: binding source port to %d, "