📄 irdpd.c
字号:
/* irdpd 1.8 - Internet router discovery protocol daemon. * Author: Kees J. Bot * 28 May 1994 * Activily solicitate or passively look for routers. * Based heavily on its forerunners, the irdp_sol and rip2icmp daemons by * Philip Homburg. */#define nil 0#include <sys/types.h>#include <errno.h>#include <fcntl.h>#include <stddef.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <limits.h>#include <unistd.h>#include <signal.h>#include <sys/ioctl.h>#include <sys/asynchio.h>#include <net/hton.h>#include <net/netlib.h>#include <net/gen/in.h>#include <net/gen/ip_hdr.h>#include <net/gen/icmp.h>#include <net/gen/icmp_hdr.h>#include <net/gen/ip_io.h>#include <net/gen/inet.h>#include <net/gen/netdb.h>#include <net/gen/oneCsum.h>#include <net/gen/socket.h>#include <net/gen/udp.h>#include <net/gen/udp_hdr.h>#include <net/gen/udp_io.h>#define MAX_RETRIES 5 /* # router solicitations. */#define TIMEOUT 4 /* Secs between solicitate retries. */#define DEST_TO (10*60) /* 10 minutes */#define NEW_ROUTE (5*60) /* 5 minutes */#define DANGER (2*60) /* Nearing a advert timeout? */#define DEAD_TO (24L*60*60) /* 24 hours */#define DEAD_PREF 0x80000000L /* from RFC 1236 */#define MaxAdvertisementInterval 450 /* 7.5 minutes */#define LifeTime (4 * MaxAdvertisementInterval)#define PRIO_OFF_DEF -1024#define RIP_VERSION 1#define RIP_REPLY 2/* It's now or never. */#define IMMEDIATELY ((time_t) ((time_t) -1 < 0 ? LONG_MIN : 0))#define NEVER ((time_t) ((time_t) -1 < 0 ? LONG_MAX : ULONG_MAX))#if !DEBUG/* Unless doing serious debugging. */#define gethostbyaddr(addr, len, type) ((struct hostent *) nil)#endif#if !__minix_vmd/* Standard Minix needs to choose between router discovery and RIP info. */int do_rdisc= 1;int do_rip= 0;#else/* VMD Minix can do both at once. */#define do_rdisc 1#define do_rip 1#endifint rip_fd; /* For incoming RIP packet. */int irdp_fd; /* Receive or transmit IRDP packets. */char *udp_device; /* UDP device to use. */char *ip_device; /* IP device to use. */int priority_offset; /* Offset to make my routes less preferred. */int bcast= 0; /* Broadcast adverts to all. */int silent= 0; /* Don't react to solicitations. */int debug= 0;char rip_buf[8192]; /* Incoming RIP packet buffer. */char irdp_buf[1024]; /* IRDP buffer. */typedef struct routeinfo{ u8_t command; u8_t version; u16_t zero1; struct routedata { u16_t family; u16_t zero2; u32_t ip_addr; u32_t zero3, zero4; u32_t metric; } data[1];} routeinfo_t;typedef struct table{ ipaddr_t tab_gw; i32_t tab_pref; time_t tab_time;} table_t;table_t *table; /* Collected table of routing info. */size_t table_size;ipaddr_t my_ip_addr; /* IP address of the local host. */int sol_retries= MAX_RETRIES;time_t next_sol= IMMEDIATELY;time_t next_advert= NEVER;time_t router_advert_valid= IMMEDIATELY;time_t now;void report(const char *label)/* irdpd: /dev/hd0: Device went up in flames */{ fprintf(stderr, "irdpd: %s: %s\n", label, strerror(errno));}void fatal(const char *label)/* irdpd: /dev/house: Taking this with it */{ report(label); exit(1);}char *addr2name(ipaddr_t host)/* Translate an IP address to a printable name. */{#if DEBUG struct hostent *hostent; hostent= gethostbyaddr((char *) &host, sizeof(host), AF_INET); return hostent == nil ? inet_ntoa(host) : hostent->h_name;#else return inet_ntoa(host);#endif}void print_table(void)/* Show the collected routing table. */{ int i; table_t *ptab; struct tm *tm; for (i= 0, ptab= table; i < table_size; i++, ptab++) { if (ptab->tab_time < now - DEAD_TO) continue; tm= localtime(&ptab->tab_time); printf("%-40s %6ld %02d:%02d:%02d\n", addr2name(ptab->tab_gw), (long) ptab->tab_pref, tm->tm_hour, tm->tm_min, tm->tm_sec); }}void advertize(ipaddr_t host)/* Send a router advert to a host. */{ char *buf, *data; ip_hdr_t *ip_hdr; icmp_hdr_t *icmp_hdr; int i; table_t *ptab; buf= malloc(sizeof(*ip_hdr) + offsetof(icmp_hdr_t, ih_dun.uhd_data) + table_size * (sizeof(ipaddr_t) + sizeof(u32_t))); if (buf == nil) fatal("heap error"); ip_hdr= (ip_hdr_t *) buf; icmp_hdr= (icmp_hdr_t *) (ip_hdr + 1); ip_hdr->ih_vers_ihl= 0x45; ip_hdr->ih_dst= host; icmp_hdr->ih_type= ICMP_TYPE_ROUTER_ADVER; icmp_hdr->ih_code= 0; icmp_hdr->ih_hun.ihh_ram.iram_na= 0; icmp_hdr->ih_hun.ihh_ram.iram_aes= 2; icmp_hdr->ih_hun.ihh_ram.iram_lt= htons(LifeTime); data= (char *) icmp_hdr->ih_dun.uhd_data; /* Collect gateway entries from the table. */ for (i= 0, ptab= table; i < table_size; i++, ptab++) { if (ptab->tab_time < now - DEAD_TO) continue; icmp_hdr->ih_hun.ihh_ram.iram_na++; if (ptab->tab_time < now - DEST_TO) ptab->tab_pref= DEAD_PREF; * (ipaddr_t *) data= ptab->tab_gw; data+= sizeof(ipaddr_t); * (i32_t *) data= htonl(ptab->tab_pref); data+= sizeof(i32_t); } icmp_hdr->ih_chksum= 0; icmp_hdr->ih_chksum= ~oneC_sum(0, icmp_hdr, data - (char *) icmp_hdr); if (icmp_hdr->ih_hun.ihh_ram.iram_na > 0) { /* Send routing info. */ if (debug) { printf("Routing table send to %s:\n", addr2name(host)); print_table(); } if (write(irdp_fd, buf, data - buf) < 0) { (errno == EIO ? fatal : report)(ip_device); } } free(buf);}void time_functions(void)/* Perform time dependend functions: router solicitation, router advert. */{ if (now >= next_sol) { char buf[sizeof(ip_hdr_t) + 8]; ip_hdr_t *ip_hdr; icmp_hdr_t *icmp_hdr; if (sol_retries == 0) { /* Stop solicitating. */ next_sol= NEVER;#if !__minix_vmd /* Switch to RIP if no router responded. */ if (table_size == 0) { do_rip= 1; do_rdisc= 0; }#endif return; } /* Broadcast a router solicitation to find a router. */ ip_hdr= (ip_hdr_t *) buf; icmp_hdr= (icmp_hdr_t *) (ip_hdr + 1); ip_hdr->ih_vers_ihl= 0x45; ip_hdr->ih_dst= HTONL(0xFFFFFFFFL); icmp_hdr->ih_type= ICMP_TYPE_ROUTE_SOL; icmp_hdr->ih_code= 0; icmp_hdr->ih_chksum= 0; icmp_hdr->ih_hun.ihh_unused= 0; icmp_hdr->ih_chksum= ~oneC_sum(0, icmp_hdr, 8); if (debug) printf("Broadcasting router solicitation\n"); if (write(irdp_fd, buf, sizeof(buf)) < 0) fatal("sending router solicitation failed"); /* Schedule the next packet. */ next_sol= now + TIMEOUT; sol_retries--; } if (now >= next_advert) { /* Advertize routes to the local host (normally), or * broadcast them (to keep bad hosts up.) */ advertize(bcast ? HTONL(0xFFFFFFFFL) : HTONL(0x7F000001L)); next_advert= now + MaxAdvertisementInterval;#if !__minix_vmd /* Make sure we are listening to RIP now. */ do_rip= 1; do_rdisc= 0;#endif }}void add_gateway(ipaddr_t host, i32_t pref)/* Add a router with given address and preference to the routing table. */{ table_t *oldest, *ptab; int i; /* Look for the host, or select the oldest entry. */ oldest= nil; for (i= 0, ptab= table; i < table_size; i++, ptab++) { if (ptab->tab_gw == host) break; if (oldest == nil || ptab->tab_time < oldest->tab_time) oldest= ptab; } /* Don't evict the oldest if it is still valid. */ if (oldest != nil && oldest->tab_time >= now - DEST_TO) oldest= nil; /* Expand the table? */ if (i == table_size && oldest == nil) { table_size++; table= realloc(table, table_size * sizeof(*table)); if (table == nil) fatal("heap error"); oldest= &table[table_size - 1]; } if (oldest != nil) { ptab= oldest; ptab->tab_gw= host; ptab->tab_pref= DEAD_PREF; } /* Replace an entry if the new one looks more promising. */ if (pref >= ptab->tab_pref || ptab->tab_time <= now - NEW_ROUTE) { ptab->tab_pref= pref; ptab->tab_time= now; }}void rip_incoming(ssize_t n)/* Use a RIP packet to add to the router table. (RIP packets are really for * between routers, but often it is the only information around.) */{ udp_io_hdr_t *udp_io_hdr; u32_t default_dist; i32_t pref; routeinfo_t *routeinfo; struct routedata *data, *end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -