📄 main.c
字号:
#include <errno.h>#include <poll.h>#include <limits.h>#include <setjmp.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <time.h>#include <arpa/inet.h>#include <sys/types.h>#include <sys/time.h>#include <dirent.h>#include <fcntl.h>#include <unistd.h> /* for getopts */#include <net/if_arp.h>#include "ipconfig.h"#include "netdev.h"#include "bootp_packet.h"#include "bootp_proto.h"#include "dhcp_proto.h"#include "packet.h"static const char sysfs_class_net[] = "/sys/class/net";static const char *progname;static jmp_buf abort_buf;static char do_not_config;static unsigned int default_caps = CAP_DHCP | CAP_BOOTP | CAP_RARP;static int loop_timeout = -1;static int configured;static int bringup_first = 0;/* DHCP vendor class identifier */char vendor_class_identifier[260];int vendor_class_identifier_len;struct state { int state; int restart_state; time_t expire; int retry_period; struct netdev *dev; struct state *next;};static inline const char *my_inet_ntoa(uint32_t addr){ struct in_addr a; a.s_addr = addr; return inet_ntoa(a);}static void print_device_config(struct netdev *dev){ printf("IP-Config: %s complete (from %s):\n", dev->name, my_inet_ntoa(dev->serverid ? dev->serverid : dev->ip_server)); printf(" address: %-16s ", my_inet_ntoa(dev->ip_addr)); printf("broadcast: %-16s ", my_inet_ntoa(dev->ip_broadcast)); printf("netmask: %-16s\n", my_inet_ntoa(dev->ip_netmask)); printf(" gateway: %-16s ", my_inet_ntoa(dev->ip_gateway)); printf("dns0 : %-16s ", my_inet_ntoa(dev->ip_nameserver[0])); printf("dns1 : %-16s\n", my_inet_ntoa(dev->ip_nameserver[1])); if (dev->hostname[0]) printf(" host : %-64s\n", dev->hostname); if (dev->dnsdomainname[0]) printf(" domain : %-64s\n", dev->dnsdomainname); if (dev->nisdomainname[0]) printf(" nisdomain: %-64s\n", dev->nisdomainname); printf(" rootserver: %s ", my_inet_ntoa(dev->ip_server)); printf("rootpath: %s\n", dev->bootpath); printf(" filename : %s\n", dev->filename);}static void configure_device(struct netdev *dev){ if (do_not_config) return; if (netdev_setmtu(dev)) printf("IP-Config: failed to set MTU on %s to %u\n", dev->name, dev->mtu); if (netdev_setaddress(dev)) printf("IP-Config: failed to set addresses on %s\n", dev->name); if (netdev_setdefaultroute(dev)) printf("IP-Config: failed to set default route on %s\n", dev->name); if (dev->hostname[0] && sethostname(dev->hostname, strlen(dev->hostname))) printf("IP-Config: failed to set hostname '%s' from %s\n", dev->hostname, dev->name);}static void dump_device_config(struct netdev *dev){ char fn[40]; FILE *f; snprintf(fn, sizeof(fn), "/tmp/net-%s.conf", dev->name); f = fopen(fn, "w"); if (f) { fprintf(f, "DEVICE=%s\n", dev->name); fprintf(f, "IPV4ADDR=%s\n", my_inet_ntoa(dev->ip_addr)); fprintf(f, "IPV4BROADCAST=%s\n", my_inet_ntoa(dev->ip_broadcast)); fprintf(f, "IPV4NETMASK=%s\n", my_inet_ntoa(dev->ip_netmask)); fprintf(f, "IPV4GATEWAY=%s\n", my_inet_ntoa(dev->ip_gateway)); fprintf(f, "IPV4DNS0=%s\n", my_inet_ntoa(dev->ip_nameserver[0])); fprintf(f, "IPV4DNS1=%s\n", my_inet_ntoa(dev->ip_nameserver[1])); fprintf(f, "HOSTNAME=%s\n", dev->hostname); fprintf(f, "DNSDOMAIN=%s\n", dev->dnsdomainname); fprintf(f, "NISDOMAIN=%s\n", dev->nisdomainname); fprintf(f, "ROOTSERVER=%s\n", my_inet_ntoa(dev->ip_server)); fprintf(f, "ROOTPATH=%s\n", dev->bootpath); fprintf(f, "filename=\"%s\"\n", dev->filename); fclose(f); }}static uint32_t inet_class_netmask(uint32_t ip){ ip = ntohl(ip); if (IN_CLASSA(ip)) return htonl(IN_CLASSA_NET); if (IN_CLASSB(ip)) return htonl(IN_CLASSB_NET); if (IN_CLASSC(ip)) return htonl(IN_CLASSC_NET); return INADDR_ANY;}static void postprocess_device(struct netdev *dev){ if (dev->ip_netmask == INADDR_ANY) { dev->ip_netmask = inet_class_netmask(dev->ip_addr); printf("IP-Config: %s guessed netmask %s\n", dev->name, my_inet_ntoa(dev->ip_netmask)); } if (dev->ip_broadcast == INADDR_ANY) { dev->ip_broadcast = (dev->ip_addr & dev->ip_netmask) | ~dev->ip_netmask; printf("IP-Config: %s guessed broadcast address %s\n", dev->name, my_inet_ntoa(dev->ip_broadcast)); } if (dev->ip_nameserver[0] == INADDR_ANY) { dev->ip_nameserver[0] = dev->ip_server; printf("IP-Config: %s guessed nameserver address %s\n", dev->name, my_inet_ntoa(dev->ip_nameserver[0])); }}static void complete_device(struct netdev *dev){ postprocess_device(dev); configure_device(dev); dump_device_config(dev); print_device_config(dev); ++configured; dev->next = ifaces; ifaces = dev;}static int process_receive_event(struct state *s, time_t now){ int handled = 1; switch (s->state) { case DEVST_BOOTP: s->restart_state = DEVST_BOOTP; switch (bootp_recv_reply(s->dev)) { case -1: s->state = DEVST_ERROR; break; case 1: s->state = DEVST_COMPLETE; DEBUG(("\n bootp reply\n")); break; } break; case DEVST_DHCPDISC: s->restart_state = DEVST_DHCPDISC; switch (dhcp_recv_offer(s->dev)) { case -1: s->state = DEVST_ERROR; break; case 1: /* Offer received */ s->state = DEVST_DHCPREQ; dhcp_send_request(s->dev); break; } break; case DEVST_DHCPREQ: s->restart_state = DEVST_DHCPDISC; switch (dhcp_recv_ack(s->dev)) { case -1: /* error */ s->state = DEVST_ERROR; break; case 1: /* ACK received */ s->state = DEVST_COMPLETE; break; case 2: /* NAK received */ s->state = DEVST_DHCPDISC; break; } break; } switch (s->state) { case DEVST_COMPLETE: complete_device(s->dev); break; case DEVST_ERROR: /* error occurred, try again in 10 seconds */ s->expire = now + 10; default: DEBUG(("\n")); handled = 0; break; } return handled;}static void process_timeout_event(struct state *s, time_t now){ int ret = 0; /* * Is the link up? If not, try again in 1 second. */ if (!netdev_running(s->dev)) { s->expire = now + 1; s->state = s->restart_state; return; } /* * If we had an error, restore a sane state to * restart from. */ if (s->state == DEVST_ERROR) s->state = s->restart_state; /* * Now send a packet depending on our state. */ switch (s->state) { case DEVST_BOOTP: ret = bootp_send_request(s->dev); s->restart_state = DEVST_BOOTP; break; case DEVST_DHCPDISC: ret = dhcp_send_discover(s->dev); s->restart_state = DEVST_DHCPDISC; break; case DEVST_DHCPREQ: ret = dhcp_send_request(s->dev); s->restart_state = DEVST_DHCPDISC; break; } if (ret == -1) { s->state = DEVST_ERROR; s->expire = now + 10; } else { s->expire = now + s->retry_period; s->retry_period *= 2; if (s->retry_period > 60) s->retry_period = 60; }}static struct state *slist;struct netdev *ifaces;static int do_pkt_recv(int pkt_fd, time_t now){ int ifindex, ret; struct state *s; ret = packet_peek(&ifindex); if (ret < 0) goto bail; for (s = slist; s; s = s->next) { if (s->dev->ifindex == ifindex) { ret |= process_receive_event(s, now); break; } } bail: return ret;}static int loop(void){#define NR_FDS 1 struct pollfd fds[NR_FDS]; struct state *s; int pkt_fd; int nr = 0; struct timeval now, prev; time_t start; pkt_fd = packet_open(); if (pkt_fd == -1) { perror("packet_open"); return -1; } fds[0].fd = pkt_fd; fds[0].events = POLLRDNORM; gettimeofday(&now, NULL); start = now.tv_sec; while (1) { int timeout = 60; int pending = 0; int done = 0; int timeout_ms; int x; for (s = slist; s; s = s->next) { DEBUG(("%s: state = %d\n", s->dev->name, s->state)); if (s->state == DEVST_COMPLETE) { done++; continue; } pending++; if (s->expire - now.tv_sec <= 0) { DEBUG(("timeout\n")); process_timeout_event(s, now.tv_sec); } if (timeout > s->expire - now.tv_sec) timeout = s->expire - now.tv_sec; } if (pending == 0 || (bringup_first && done)) break; timeout_ms = timeout * 1000; for (x = 0; x < 2; x++) { int delta_ms; if (timeout_ms <= 0) timeout_ms = 100; nr = poll(fds, NR_FDS, timeout_ms); prev = now; gettimeofday(&now, NULL); if ((fds[0].revents & POLLRDNORM)) { nr = do_pkt_recv(pkt_fd, now.tv_sec); if (nr == 1) break; else if (nr == 0) packet_discard(); } if (loop_timeout >= 0 && now.tv_sec - start >= loop_timeout) { printf("IP-Config: no response after %d " "secs - giving up\n", loop_timeout); goto bail; } delta_ms = (now.tv_sec - prev.tv_sec) * 1000; delta_ms += (now.tv_usec - prev.tv_usec) / 1000; DEBUG(("Delta: %d ms\n", delta_ms)); timeout_ms -= delta_ms; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -