void radvd_process() { unsigned char msg[MSG_SIZE]; int len, hoplimit; struct sockaddr_in6 rcv_addr; struct in6_pktinfo *pkt_info = NULL; len = recv_rs_ra(sock, msg, &rcv_addr, &pkt_info, &hoplimit); if (len > 0) process(sock, iface, msg, len, &rcv_addr, pkt_info, hoplimit); }
int main(int argc, char *argv[]) { unsigned char msg[MSG_SIZE]; char pidstr[16]; ssize_t ret; int c, log_method; char *logfile, *pidfile; sigset_t oset, nset; int facility, fd; char *username = NULL; char *chrootdir = NULL; int singleprocess = 0; #ifdef HAVE_GETOPT_LONG int opt_idx; #endif /* BEGIN: Added by z67728, 2009/10/19 */ FILE * pidfp = NULL; int pid = 0; /* END: Added by z67728, 2009/10/19 */ /*start: 用于查询组件版本号(dns atpv),请不要修改或删除*/ /*if ((argc == 2) && (NULL != argv[1]) && (0 == strcmp(argv[1],ATP_VERSION_CMD_KEY))) { printf("\r\n%s.\n", RADVD_MODULE_VERSION); exit(0); }*/ /*end */ pname = ((pname=strrchr(argv[0],'/')) != NULL)?pname+1:argv[0]; srand((unsigned int)time(NULL)); log_method = L_STDERR_SYSLOG; /*BEGIN PN:2071008409 l00170266 for var problem modify 20120725 */ #define RADVD_LOG (ROUTER_VARPATH_PREFIX "/radvd/radvd.log") #define RADVD_CONF (ROUTER_VARPATH_PREFIX "/radvd/radvd.conf") #define RADVD_PID (ROUTER_VARPATH_PREFIX "/radvd/radvd.pid") logfile = RADVD_LOG; conf_file = RADVD_CONF; facility = LOG_FACILITY; pidfile = RADVD_PID; /*END PN:2071008409 l00170266 for var problem modify 20120725 */ /* parse args */ #ifdef HAVE_GETOPT_LONG while ((c = getopt_long(argc, argv, "d:C:l:m:p:t:u:vhs", prog_opt, &opt_idx)) > 0) #else while ((c = getopt(argc, argv, "d:C:l:m:p:t:u:vhs")) > 0) #endif { switch (c) { case 'C': conf_file = optarg; break; case 'd': set_debuglevel(atoi(optarg)); break; case 'f': facility = atoi(optarg); break; case 'l': logfile = optarg; break; case 'p': pidfile = optarg; break; case 'm': if (!strcmp(optarg, "syslog")) { log_method = L_SYSLOG; } else if (!strcmp(optarg, "stderr_syslog")) { log_method = L_STDERR_SYSLOG; } else if (!strcmp(optarg, "stderr")) { log_method = L_STDERR; } else if (!strcmp(optarg, "logfile")) { log_method = L_LOGFILE; } else if (!strcmp(optarg, "none")) { log_method = L_NONE; } else { fprintf(stderr, "%s: unknown log method: %s\n", pname, optarg); exit(1); } break; case 't': chrootdir = strdup(optarg); break; case 'u': username = strdup(optarg); break; case 'v': /* BEGIN 3061302357 y00188255 2013-6-28 Modified */ //version(); printf("%s\n", RADVD_MODULE_VERSION); printf("BUILTTIME is: %s %s\n",__DATE__,__TIME__); exit(1); /* END 3061302357 y00188255 2013-6-28 Modified */ break; case 's': singleprocess = 1; break; case 'h': usage(); #ifdef HAVE_GETOPT_LONG case ':': fprintf(stderr, "%s: option %s: parameter expected\n", pname, prog_opt[opt_idx].name); exit(1); #endif case '?': exit(1); } } if (chrootdir) { if (!username) { fprintf(stderr, "Chroot as root is not safe, exiting\n"); exit(1); } if (chroot(chrootdir) == -1) { perror("chroot"); exit (1); } if (chdir("/") == -1) { perror("chdir"); exit (1); } /* username will be switched later */ } if (log_open(log_method, pname, logfile, facility) < 0) exit(1); flog(LOG_INFO, "version %s started", VERSION); /* get a raw socket for sending and receiving ICMPv6 messages */ sock = open_icmpv6_socket(); if (sock < 0) exit(1); #if 0 /* check that 'other' cannot write the file * for non-root, also that self/own group can't either */ if (check_conffile_perm(username, conf_file) < 0) { if (get_debuglevel() == 0) exit(1); else flog(LOG_WARNING, "Insecure file permissions, but continuing anyway"); } /* if we know how to do it, check whether forwarding is enabled */ if (check_ip6_forwarding()) { if (get_debuglevel() == 0) { flog(LOG_ERR, "IPv6 forwarding seems to be disabled, exiting"); exit(1); } else flog(LOG_WARNING, "IPv6 forwarding seems to be disabled, but continuing anyway."); } #endif /* parse config file */ if (readin_config(conf_file) < 0){ if ( 0 != unlink(pidfile) ){ printf("\r\n Delete %s meet error. error : %s .",pidfile,strerror(errno)); } exit(1); } /* drop root privileges if requested. */ if (username) { if (!singleprocess) { dlog(LOG_DEBUG, 3, "Initializing privsep"); if (privsep_init() < 0) flog(LOG_WARNING, "Failed to initialize privsep."); } if (drop_root_privileges(username) < 0) exit(1); } #if 0 if ((fd = open(pidfile, O_RDONLY, 0)) > 0) { ret = read(fd, pidstr, sizeof(pidstr) - 1); if (ret < 0) { flog(LOG_ERR, "cannot read radvd pid file, terminating: %s", strerror(errno)); exit(1); } pidstr[ret] = '\0'; if (!kill((pid_t)atol(pidstr), 0)) { flog(LOG_ERR, "radvd already running, terminating."); exit(1); } close(fd); fd = open(pidfile, O_CREAT|O_TRUNC|O_WRONLY, 0644); } else /* FIXME: not atomic if pidfile is on an NFS mounted volume */ fd = open(pidfile, O_CREAT|O_EXCL|O_WRONLY, 0644); if (fd < 0) { flog(LOG_ERR, "cannot create radvd pid file, terminating: %s", strerror(errno)); exit(1); } #endif /* * okay, config file is read in, socket and stuff is setup, so * lets fork now... */ #if 0 if (get_debuglevel() == 0) { /* Detach from controlling terminal */ if (daemon(0, 0) < 0) perror("daemon"); /* close old logfiles, including stderr */ log_close(); /* reopen logfiles, but don't log to stderr unless explicitly requested */ if (log_method == L_STDERR_SYSLOG) log_method = L_SYSLOG; if (log_open(log_method, pname, logfile, facility) < 0) exit(1); } #endif /* * config signal handlers, also make sure ALRM isn't blocked and raise a warning if so * (some stupid scripts/pppd appears to do this...) */ sigemptyset(&nset); sigaddset(&nset, SIGALRM); sigprocmask(SIG_UNBLOCK, &nset, &oset); if (sigismember(&oset, SIGALRM)) flog(LOG_WARNING, "SIGALRM has been unblocked. Your startup environment might be wrong."); signal(SIGHUP, sighup_handler); signal(SIGTERM, sigterm_handler); signal(SIGINT, sigint_handler); /* BEGIN: Added by z67728, 2009/11/3 */ signal(SIGUSR1, sigdebug_handler); signal(SIGUSR2, sigprefixchg_handler); /* END: Added by z67728, 2009/11/3 */ #if 0 snprintf(pidstr, sizeof(pidstr), "%ld\n", (long)getpid()); write(fd, pidstr, strlen(pidstr)); close(fd); #endif /*BEGIN PN:2071008409 l00170266 for var problem modify 20120725 */ #define RADVD_READTEST (ROUTER_VARPATH_PREFIX "/radvd/readtest") if ( 0 == access(RADVD_READTEST,F_OK) ) /*END PN:2071008409 l00170266 for var problem modify 20120725 */ { /* Ready test */ g_iReadTestFlag = 1; } pid = getpid(); if ((pidfp = fopen(pidfile, "w")) != NULL) { fwrite(&pid,1,4,pidfp); fclose(pidfp); } config_interface(); kickoff_adverts(); /* enter loop */ for (;;) { int len = 0, hoplimit = 0; struct sockaddr_in6 rcv_addr; struct in6_pktinfo *pkt_info = NULL; len = recv_rs_ra(sock, msg, &rcv_addr, &pkt_info, &hoplimit); if (len > 0) { process(sock, IfaceList, msg, len, &rcv_addr, pkt_info, hoplimit); } if (sigterm_received || sigint_received) { stop_adverts(); break; } if (sighup_received) { if ( 1 == g_iPrefixChgeFlag ) { disable_oldprefix(); } reload_config(); sighup_received = 0; g_iPrefixChgeFlag = 0; } } unlink(pidfile); exit(0); }
int main(int argc, char *argv[]) { unsigned char msg[MSG_SIZE]; char pidstr[16]; ssize_t ret; int c, log_method; char *logfile, *pidfile; sigset_t oset, nset; int facility, fd; char *username = NULL; char *chrootdir = NULL; int singleprocess = 0; #ifdef HAVE_GETOPT_LONG int opt_idx; #endif pname = ((pname=strrchr(argv[0],'/')) != NULL)?pname+1:argv[0]; srand((unsigned int)time(NULL)); log_method = L_STDERR_SYSLOG; logfile = PATH_RADVD_LOG; conf_file = PATH_RADVD_CONF; facility = LOG_FACILITY; pidfile = PATH_RADVD_PID; /* parse args */ #ifdef HAVE_GETOPT_LONG /* Add option to show advertise real lifetime */ /* while ((c = getopt_long(argc, argv, "d:C:l:m:p:t:u:vhs", prog_opt, &opt_idx)) > 0) */ while ((c = getopt_long(argc, argv, "d:C:l:m:p:t:u:vhsD", prog_opt, &opt_idx)) > 0) #else /* Add option to show advertise real lifetime */ /* while ((c = getopt(argc, argv, "d:C:l:m:p:t:u:vhs")) > 0) */ while ((c = getopt(argc, argv, "d:C:l:m:p:t:u:vhsD")) > 0) #endif { switch (c) { case 'C': conf_file = optarg; break; case 'd': set_debuglevel(atoi(optarg)); break; case 'f': facility = atoi(optarg); break; case 'l': logfile = optarg; break; case 'p': pidfile = optarg; break; case 'm': if (!strcmp(optarg, "syslog")) { log_method = L_SYSLOG; } else if (!strcmp(optarg, "stderr_syslog")) { log_method = L_STDERR_SYSLOG; } else if (!strcmp(optarg, "stderr")) { log_method = L_STDERR; } else if (!strcmp(optarg, "logfile")) { log_method = L_LOGFILE; } else if (!strcmp(optarg, "none")) { log_method = L_NONE; } else { fprintf(stderr, "%s: unknown log method: %s\n", pname, optarg); exit(1); } break; case 't': chrootdir = strdup(optarg); break; case 'u': username = strdup(optarg); break; case 'v': version(); break; case 's': singleprocess = 1; break; /* Add option to show advertise dynamic lifetime */ case 'D': use_dynamic_lifetime = 1; break; case 'h': usage(); #ifdef HAVE_GETOPT_LONG case ':': fprintf(stderr, "%s: option %s: parameter expected\n", pname, prog_opt[opt_idx].name); exit(1); #endif case '?': exit(1); } } if (chrootdir) { if (!username) { fprintf(stderr, "Chroot as root is not safe, exiting\n"); exit(1); } if (chroot(chrootdir) == -1) { perror("chroot"); exit (1); } if (chdir("/") == -1) { perror("chdir"); exit (1); } /* username will be switched later */ } if (log_open(log_method, pname, logfile, facility) < 0) exit(1); flog(LOG_INFO, "version %s started", VERSION); /* get a raw socket for sending and receiving ICMPv6 messages */ sock = open_icmpv6_socket(); if (sock < 0) exit(1); /* check that 'other' cannot write the file * for non-root, also that self/own group can't either */ if (check_conffile_perm(username, conf_file) < 0) { if (get_debuglevel() == 0) exit(1); else flog(LOG_WARNING, "Insecure file permissions, but continuing anyway"); } /* if we know how to do it, check whether forwarding is enabled */ if (check_ip6_forwarding()) { if (get_debuglevel() == 0) { flog(LOG_ERR, "IPv6 forwarding seems to be disabled, exiting"); exit(1); } else flog(LOG_WARNING, "IPv6 forwarding seems to be disabled, but continuing anyway."); } /* parse config file */ if (readin_config(conf_file) < 0) exit(1); /* drop root privileges if requested. */ if (username) { if (!singleprocess) { dlog(LOG_DEBUG, 3, "Initializing privsep"); if (privsep_init() < 0) flog(LOG_WARNING, "Failed to initialize privsep."); } if (drop_root_privileges(username) < 0) exit(1); } if ((fd = open(pidfile, O_RDONLY, 0)) > 0) { ret = read(fd, pidstr, sizeof(pidstr) - 1); if (ret < 0) { flog(LOG_ERR, "cannot read radvd pid file, terminating: %s", strerror(errno)); exit(1); } pidstr[ret] = '\0'; if (!kill((pid_t)atol(pidstr), 0)) { flog(LOG_ERR, "radvd already running, terminating."); exit(1); } close(fd); fd = open(pidfile, O_CREAT|O_TRUNC|O_WRONLY, 0644); } else /* FIXME: not atomic if pidfile is on an NFS mounted volume */ fd = open(pidfile, O_CREAT|O_EXCL|O_WRONLY, 0644); if (fd < 0) { flog(LOG_ERR, "cannot create radvd pid file, terminating: %s", strerror(errno)); exit(1); } /* * okay, config file is read in, socket and stuff is setup, so * lets fork now... */ if (get_debuglevel() == 0) { /* Detach from controlling terminal */ if (daemon(0, 0) < 0) perror("daemon"); /* close old logfiles, including stderr */ log_close(); /* reopen logfiles, but don't log to stderr unless explicitly requested */ if (log_method == L_STDERR_SYSLOG) log_method = L_SYSLOG; if (log_open(log_method, pname, logfile, facility) < 0) exit(1); } /* * config signal handlers, also make sure ALRM isn't blocked and raise a warning if so * (some stupid scripts/pppd appears to do this...) */ sigemptyset(&nset); sigaddset(&nset, SIGALRM); sigprocmask(SIG_UNBLOCK, &nset, &oset); if (sigismember(&oset, SIGALRM)) flog(LOG_WARNING, "SIGALRM has been unblocked. Your startup environment might be wrong."); signal(SIGHUP, sighup_handler); signal(SIGTERM, sigterm_handler); signal(SIGINT, sigint_handler); signal(SIGUSR1, sigusr1_handler); snprintf(pidstr, sizeof(pidstr), "%ld\n", (long)getpid()); write(fd, pidstr, strlen(pidstr)); close(fd); config_interface(); /* Record the time for first advertisement */ set_initial_advert_time(); kickoff_adverts(); /* enter loop */ for (;;) { int len, hoplimit; struct sockaddr_in6 rcv_addr; struct in6_pktinfo *pkt_info = NULL; len = recv_rs_ra(sock, msg, &rcv_addr, &pkt_info, &hoplimit); if (len > 0) process(sock, IfaceList, msg, len, &rcv_addr, pkt_info, hoplimit); if (sigterm_received || sigint_received) { stop_adverts(); /* WNR3500L TD192, Per Netgear spec, * need to send RA for 3 times before termination. */ usleep(200000); stop_adverts(); usleep(200000); stop_adverts(); break; } if (sighup_received) { reload_config(); sighup_received = 0; } /* Reset the initial advertisement time to now */ /* This should happen after a successful IADP renew */ if (sigusr1_received) { set_initial_advert_time(); sigusr1_received = 0; } } unlink(pidfile); exit(0); }
void main_loop(void) { struct pollfd fds[2]; memset(fds, 0, sizeof(fds)); fds[0].fd = sock; fds[0].events = POLLIN; fds[0].revents = 0; #if HAVE_NETLINK fds[1].fd = netlink_socket(); fds[1].events = POLLIN; fds[1].revents = 0; #else fds[1].fd = -1; fds[1].events = 0; fds[1].revents = 0; #endif for (;;) { struct Interface *next = NULL; struct Interface *iface; int timeout = -1; int rc; if (IfaceList) { timeout = next_time_msec(IfaceList); next = IfaceList; for (iface = IfaceList; iface; iface = iface->next) { int t; t = next_time_msec(iface); if (timeout > t) { timeout = t; next = iface; } } } dlog(LOG_DEBUG, 5, "polling for %g seconds.", timeout/1000.0); rc = poll(fds, sizeof(fds)/sizeof(fds[0]), timeout); if (rc > 0) { if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { flog(LOG_WARNING, "socket error on fds[0].fd"); } else if (fds[0].revents & POLLIN) { int len, hoplimit; struct sockaddr_in6 rcv_addr; struct in6_pktinfo *pkt_info = NULL; unsigned char msg[MSG_SIZE_RECV]; len = recv_rs_ra(msg, &rcv_addr, &pkt_info, &hoplimit); if (len > 0) { process(IfaceList, msg, len, &rcv_addr, pkt_info, hoplimit); } } #ifdef HAVE_NETLINK if (fds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) { flog(LOG_WARNING, "socket error on fds[1].fd"); } else if (fds[1].revents & POLLIN) { process_netlink_msg(fds[1].fd); } #endif } else if ( rc == 0 ) { if (next) timer_handler(next); } else if ( rc == -1 && errno != EINTR ) { flog(LOG_ERR, "poll error: %s", strerror(errno)); } if (sigterm_received || sigint_received) { flog(LOG_WARNING, "Exiting, sigterm or sigint received.\n"); break; } if (sighup_received) { reload_config(); sighup_received = 0; } if (sigusr1_received) { reset_prefix_lifetimes(); sigusr1_received = 0; } } }
int main(int argc, char *argv[]) { unsigned char msg[MSG_SIZE]; int c, len, hoplimit; int fform = 0; int edefs = 0; struct sockaddr_in6 rcv_addr; struct in6_pktinfo *pkt_info = NULL; #ifdef HAVE_GETOPT_LONG int opt_idx; #endif pname = ((pname=strrchr(argv[0],'/')) != NULL)?pname+1:argv[0]; /* parse args */ #ifdef HAVE_GETOPT_LONG while ((c = getopt_long(argc, argv, "d:fehv", prog_opt, &opt_idx)) > 0) #else while ((c = getopt(argc, argv, "d:fehv")) > 0) #endif { switch (c) { case 'd': set_debuglevel(atoi(optarg)); break; case 'f': fform = 1; break; case 'e': edefs = 1; break; case 'v': version(); break; case 'h': usage(); #ifdef HAVE_GETOPT_LONG case ':': fprintf(stderr, "%s: option %s: parameter expected\n", pname, prog_opt[opt_idx].name); exit(1); #endif case '?': exit(1); } } if (log_open(L_STDERR, pname, NULL, 0) < 0) exit(1); /* get a raw socket for sending and receiving ICMPv6 messages */ sock = open_icmpv6_socket(); if (sock < 0) exit(1); for(;;) { len = recv_rs_ra(sock, msg, &rcv_addr, &pkt_info, &hoplimit); if (len > 0) { struct icmp6_hdr *icmph; /* * can this happen? */ if (len < sizeof(struct icmp6_hdr)) { log(LOG_WARNING, "received icmpv6 packet with invalid length: %d", len); exit(1); } icmph = (struct icmp6_hdr *) msg; if (icmph->icmp6_type != ND_ROUTER_SOLICIT && icmph->icmp6_type != ND_ROUTER_ADVERT) { /* * We just want to listen to RSs and RAs */ log(LOG_ERR, "icmpv6 filter failed"); exit(1); } dlog(LOG_DEBUG, 4, "receiver if_index: %d", pkt_info->ipi6_ifindex); if (icmph->icmp6_type == ND_ROUTER_SOLICIT) { /* not yet */ } else if (icmph->icmp6_type == ND_ROUTER_ADVERT) { if (!fform) print_ra(msg, len, &rcv_addr, hoplimit, pkt_info->ipi6_ifindex); else print_ff(msg, len, &rcv_addr, hoplimit, pkt_info->ipi6_ifindex, edefs); } } else if (len == 0) { log(LOG_ERR, "received zero lenght packet"); exit(1); } else { log(LOG_ERR, "recv_rs_ra: %s", strerror(errno)); exit(1); } } exit(0); }
static struct Interface * main_loop(int sock, struct Interface *ifaces, char const *conf_path) { struct pollfd fds[2]; sigset_t sigmask; sigset_t sigempty; struct sigaction sa; sigemptyset(&sigempty); sigemptyset(&sigmask); sigaddset(&sigmask, SIGHUP); sigaddset(&sigmask, SIGTERM); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGUSR1); sigprocmask(SIG_BLOCK, &sigmask, NULL); sa.sa_handler = sighup_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGHUP, &sa, 0); sa.sa_handler = sigterm_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGTERM, &sa, 0); sa.sa_handler = sigint_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGINT, &sa, 0); sa.sa_handler = sigusr1_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGUSR1, &sa, 0); memset(fds, 0, sizeof(fds)); fds[0].fd = sock; fds[0].events = POLLIN; #if HAVE_NETLINK fds[1].fd = netlink_socket(); fds[1].events = POLLIN; #else fds[1].fd = -1; #endif for (;;) { struct timespec *tsp = 0; struct Interface *next_iface_to_expire = find_iface_by_time(ifaces); if (next_iface_to_expire) { static struct timespec ts; int timeout = next_time_msec(next_iface_to_expire); ts.tv_sec = timeout / 1000; ts.tv_nsec = (timeout - 1000 * ts.tv_sec) * 1000000; tsp = &ts; dlog(LOG_DEBUG, 1, "polling for %g second(s), next iface is %s", timeout / 1000.0, next_iface_to_expire->props.name); } else { dlog(LOG_DEBUG, 1, "no iface is next. Polling indefinitely"); } #ifdef HAVE_PPOLL int rc = ppoll(fds, sizeof(fds) / sizeof(fds[0]), tsp, &sigempty); #else int rc = poll(fds, sizeof(fds) / sizeof(fds[0]), 1000*tsp->tv_sec); #endif if (rc > 0) { #ifdef HAVE_NETLINK if (fds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) { flog(LOG_WARNING, "socket error on fds[1].fd"); } else if (fds[1].revents & POLLIN) { process_netlink_msg(fds[1].fd, ifaces); } #endif if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { flog(LOG_WARNING, "socket error on fds[0].fd"); } else if (fds[0].revents & POLLIN) { int len, hoplimit; struct sockaddr_in6 rcv_addr; struct in6_pktinfo *pkt_info = NULL; unsigned char msg[MSG_SIZE_RECV]; unsigned char chdr[CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int))]; len = recv_rs_ra(sock, msg, &rcv_addr, &pkt_info, &hoplimit, chdr); if (len > 0 && pkt_info) { process(sock, ifaces, msg, len, &rcv_addr, pkt_info, hoplimit); } else if (!pkt_info) { dlog(LOG_INFO, 4, "recv_rs_ra returned null pkt_info"); } else if (len <= 0) { dlog(LOG_INFO, 4, "recv_rs_ra returned len <= 0: %d", len); } } } else if (rc == 0) { if (next_iface_to_expire) timer_handler(sock, next_iface_to_expire); } else if (rc == -1) { dlog(LOG_INFO, 3, "poll returned early: %s", strerror(errno)); } if (sigint_received) { flog(LOG_WARNING, "exiting, %d sigint(s) received", sigint_received); break; } if (sigterm_received) { flog(LOG_WARNING, "exiting, %d sigterm(s) received", sigterm_received); break; } if (sighup_received) { dlog(LOG_INFO, 3, "sig hup received"); ifaces = reload_config(sock, ifaces, conf_path); sighup_received = 0; } if (sigusr1_received) { dlog(LOG_INFO, 3, "sig usr1 received"); reset_prefix_lifetimes(ifaces); sigusr1_received = 0; } } return ifaces; }