📄 irdpd.c
字号:
/* We don't care about RIP packets when there are router adverts. */ if (now + MaxAdvertisementInterval < router_advert_valid) return; udp_io_hdr= (udp_io_hdr_t *) rip_buf; if (udp_io_hdr->uih_data_len != n - sizeof(*udp_io_hdr)) { if (debug) printf("Bad sized route packet (discarded)\n"); return; } routeinfo= (routeinfo_t *) (rip_buf + sizeof(*udp_io_hdr) + udp_io_hdr->uih_ip_opt_len); if (routeinfo->version != RIP_VERSION || routeinfo->command != RIP_REPLY) { if (debug) { printf("Route packet command %d, version %d ignored\n", routeinfo->command, routeinfo->version); } return; } /* Look for a default route, the route to the gateway. */ end= (struct routedata *) (rip_buf + n); default_dist= (u32_t) -1; for (data= routeinfo->data; data < end; data++) { if (ntohs(data->family) != AF_INET || data->ip_addr != 0) continue; default_dist= ntohl(data->metric); if (default_dist >= 256) { if (debug) printf("Strange metric %d\n", default_dist); } } pref= default_dist >= 256 ? 1 : 512 - default_dist; pref+= priority_offset; /* Add the gateway to the table with the calculated preference. */ add_gateway(udp_io_hdr->uih_src_addr, pref); if (debug) { printf("Routing table after RIP packet from %s:\n", addr2name(udp_io_hdr->uih_src_addr)); print_table(); } /* Start advertizing. */ if (next_advert == NEVER) next_advert= IMMEDIATELY;}void irdp_incoming(ssize_t n)/* Look for router solicitations and router advertisements. The solicitations * are probably from other irdpd daemons, we answer them if we do not expect * a real router to answer. The advertisements cause this daemon to shut up. */{ ip_hdr_t *ip_hdr; icmp_hdr_t *icmp_hdr; int ip_hdr_len; char *data; int i; int router; ipaddr_t addr; i32_t pref; time_t valid; ip_hdr= (ip_hdr_t *) irdp_buf; ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2; if (n < ip_hdr_len + 8) { if (debug) printf("Bad sized ICMP (discarded)\n"); return; } icmp_hdr= (icmp_hdr_t *)(irdp_buf + ip_hdr_len); /* Did I send it myself? */ if (ip_hdr->ih_src == my_ip_addr) return; if ((htonl(ip_hdr->ih_src) & 0xFF000000L) == 0x7F000000L) return; if (icmp_hdr->ih_type == ICMP_TYPE_ROUTE_SOL) { /* Some other host is looking for a router. Send a table * if there is no smart router around, we are not still * solicitating ourselves, and we are not told to be silent. */ if (sol_retries == 0 && table_size > 0 && now > router_advert_valid && !silent) { advertize(ip_hdr->ih_src); } return; } if (icmp_hdr->ih_type != ICMP_TYPE_ROUTER_ADVER) return; /* Incoming router advertisement, the kind of packet the TCP/IP task * is very happy with. No need to solicit further. */ sol_retries= 0; /* Add router info to our table. Also see if the packet came from * a router, and not another irdpd. If it is from a router then we * go silent for the lifetime of the ICMP. */ router= 0; data= (char *) icmp_hdr->ih_dun.uhd_data; for (i= 0; i < icmp_hdr->ih_hun.ihh_ram.iram_na; i++) { addr= * (ipaddr_t *) data; data+= sizeof(ipaddr_t); pref= htonl(* (i32_t *) data); data+= sizeof(i32_t); if (addr == ip_hdr->ih_src) { /* The sender is in the routing table! */ router= 1; } add_gateway(addr, pref); } valid= now + ntohs(icmp_hdr->ih_hun.ihh_ram.iram_lt); if (router) router_advert_valid= valid; /* Restart advertizing close to the timeout of the advert. (No more * irdpd adverts if the router stays alive.) */ if (router || next_advert > valid - DANGER) next_advert= valid - DANGER; if (debug) { printf("Routing table after advert received from %s:\n", addr2name(ip_hdr->ih_src)); print_table(); if (router) { struct tm *tm= localtime(&router_advert_valid); printf( "This router advert is valid until %02d:%02d:%02d\n", tm->tm_hour, tm->tm_min, tm->tm_sec); } }}void sig_handler(int sig)/* A signal changes the debug level. */{ switch (sig) { case SIGUSR1: debug++; break; case SIGUSR2: debug= 0; break; }}void usage(void){ fprintf(stderr,"Usage: irdpd [-d] [-U udp-device] [-I ip-device] [-o priority-offset]\n"); exit(1);}int main(int argc, char **argv){ int i; struct servent *service; udpport_t route_port; nwio_udpopt_t udpopt; nwio_ipconf_t ipconf; nwio_ipopt_t ipopt; asynchio_t asyn; time_t timeout; struct timeval tv; struct sigaction sa; char *offset_arg, *offset_end; long arg; udp_device = ip_device = nil; for (i = 1; i < argc && argv[i][0] == '-'; i++) { char *p= argv[i] + 1; if (p[0] == '-' && p[1] == 0) { i++; break; } while (*p != 0) { switch (*p++) { case 'U': if (udp_device != nil) usage(); if (*p == 0) { if (++i == argc) usage(); p= argv[i]; } udp_device= p; p= ""; break; case 'I': if (ip_device != nil) usage(); if (*p == 0) { if (++i == argc) usage(); p= argv[i]; } ip_device= p; p= ""; break; case 'o': if (offset_arg != nil) usage(); if (*p == 0) { if (++i == argc) usage(); p= argv[i]; } offset_arg= p; p= ""; break; case 'b': bcast= 1; break; case 's': silent= 1; break; case 'd': debug= 1; break; default: usage(); } } } if (i != argc) usage(); /* Debug level signals. */ sa.sa_handler= sig_handler; sigemptyset(&sa.sa_mask); sa.sa_flags= 0; sigaction(SIGUSR1, &sa, nil); sigaction(SIGUSR2, &sa, nil); if (udp_device == nil && (udp_device= getenv("UDP_DEVICE")) == nil) udp_device= UDP_DEVICE; if (ip_device == nil && (ip_device= getenv("IP_DEVICE")) == nil) ip_device= IP_DEVICE; if (offset_arg == nil) { priority_offset= PRIO_OFF_DEF; } else { arg= strtol(offset_arg, &offset_end, 0); if (*offset_end != 0 || (priority_offset= arg) != arg) usage(); } if ((service= getservbyname("route", "udp")) == nil) { fprintf(stderr, "irdpd: unable to look up the port number for the 'route' service\n"); exit(1); } route_port= (udpport_t) service->s_port; if ((rip_fd= open(udp_device, O_RDWR)) < 0) fatal(udp_device); udpopt.nwuo_flags= NWUO_COPY | NWUO_LP_SET | NWUO_DI_LOC | NWUO_EN_BROAD | NWUO_RP_SET | NWUO_RA_ANY | NWUO_RWDATALL | NWUO_DI_IPOPT; udpopt.nwuo_locport= route_port; udpopt.nwuo_remport= route_port; if (ioctl(rip_fd, NWIOSUDPOPT, &udpopt) < 0) fatal("setting UDP options failed"); if ((irdp_fd= open(ip_device, O_RDWR)) < 0) fatal(ip_device); if (ioctl(irdp_fd, NWIOGIPCONF, &ipconf) < 0) fatal("can't get IP configuration"); my_ip_addr= ipconf.nwic_ipaddr; ipopt.nwio_flags= NWIO_COPY | NWIO_EN_LOC | NWIO_EN_BROAD | NWIO_REMANY | NWIO_PROTOSPEC | NWIO_HDR_O_SPEC | NWIO_RWDATALL; ipopt.nwio_tos= 0; ipopt.nwio_ttl= 255; ipopt.nwio_df= 0; ipopt.nwio_hdropt.iho_opt_siz= 0; ipopt.nwio_rem= HTONL(0xFFFFFFFFL); ipopt.nwio_proto= IPPROTO_ICMP; if (ioctl(irdp_fd, NWIOSIPOPT, &ipopt) < 0) fatal("can't configure ICMP channel"); asyn_init(&asyn); while (1) { ssize_t r; if (do_rip) { /* Try a RIP read. */ r= asyn_read(&asyn, rip_fd, rip_buf, sizeof(rip_buf)); if (r < 0) { if (errno == EIO) fatal(udp_device); if (errno != EINPROGRESS) report(udp_device); } else { now= time(nil); rip_incoming(r); } } if (do_rdisc) { /* Try an IRDP read. */ r= asyn_read(&asyn, irdp_fd, irdp_buf, sizeof(irdp_buf)); if (r < 0) { if (errno == EIO) fatal(ip_device); if (errno != EINPROGRESS) report(ip_device); } else { now= time(nil); irdp_incoming(r); } } fflush(stdout); /* Compute the next wakeup call. */ timeout= next_sol < next_advert ? next_sol : next_advert; /* Wait for a RIP or IRDP packet or a timeout. */ tv.tv_sec= timeout; tv.tv_usec= 0; if (asyn_wait(&asyn, 0, timeout == NEVER ? nil : &tv) < 0) { /* Timeout? */ if (errno != EINTR && errno != EAGAIN) fatal("asyn_wait()"); now= time(nil); time_functions(); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -