示例#1
0
/* The public function to return random data of the quality LEVEL.
   Returns a pointer to a newly allocated and randomized buffer of
   LEVEL and NBYTES length.  Caller must free the buffer.  */
void *
gcry_random_bytes (size_t nbytes, enum gcry_random_level level)
{
  void *buffer;

  buffer = gcry_xmalloc (nbytes);
  do_randomize (buffer, nbytes, level);
  return buffer;
}
示例#2
0
/* The public function to return random data of the quality LEVEL;
   this version of the function returns the random in a buffer allocated
   in secure memory.  Caller must free the buffer. */
void *
gcry_random_bytes_secure (size_t nbytes, enum gcry_random_level level)
{
  void *buffer;

  /* Historical note (1.3.0--1.4.1): The buffer was only allocated
     in secure memory if the pool in random-csprng.c was also set to
     use secure memory.  */
  buffer = gcry_xmalloc_secure (nbytes);
  do_randomize (buffer, nbytes, level);
  return buffer;
}
示例#3
0
/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */
void
gcry_create_nonce (void *buffer, size_t length)
{
  static unsigned char nonce_buffer[20+8];
  static int nonce_buffer_initialized = 0;
  static volatile pid_t my_pid; /* The volatile is there to make sure the
                                   compiler does not optimize the code away
                                   in case the getpid function is badly
                                   attributed. */
  volatile pid_t apid;
  unsigned char *p;
  size_t n;
  int err;

  /* First check whether we shall use the FIPS nonce generator.  This
     is only done in FIPS mode, in all other modes, we use our own
     nonce generator which is seeded by the RNG actual in use.  */
  if (fips_mode ())
    {
      _gcry_rngfips_create_nonce (buffer, length);
      return;
    }

  /* This is the nonce generator, which formerly lived in
     random-csprng.c.  It is now used by all RNG types except when in
     FIPS mode (not that this means it is also used if the FIPS RNG
     has been selected but we are not in fips mode).  */

  /* Make sure we are initialized. */
  _gcry_random_initialize (1);

  /* Acquire the nonce buffer lock. */
  err = ath_mutex_lock (&nonce_buffer_lock);
  if (err)
    log_fatal ("failed to acquire the nonce buffer lock: %s\n",
               strerror (err));

  apid = getpid ();
  /* The first time initialize our buffer. */
  if (!nonce_buffer_initialized)
    {
      time_t atime = time (NULL);
      pid_t xpid = apid;

      my_pid = apid;

      if ((sizeof apid + sizeof atime) > sizeof nonce_buffer)
        BUG ();

      /* Initialize the first 20 bytes with a reasonable value so that
         a failure of gcry_randomize won't affect us too much.  Don't
         care about the uninitialized remaining bytes. */
      p = nonce_buffer;
      memcpy (p, &xpid, sizeof xpid);
      p += sizeof xpid;
      memcpy (p, &atime, sizeof atime);

      /* Initialize the never changing private part of 64 bits. */
      gcry_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM);

      nonce_buffer_initialized = 1;
    }
  else if ( my_pid != apid )
    {
      /* We forked. Need to reseed the buffer - doing this for the
         private part should be sufficient. */
      do_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM);
      /* Update the pid so that we won't run into here again and
         again. */
      my_pid = apid;
    }

  /* Create the nonce by hashing the entire buffer, returning the hash
     and updating the first 20 bytes of the buffer with this hash. */
  for (p = buffer; length > 0; length -= n, p += n)
    {
      _gcry_sha1_hash_buffer (nonce_buffer,
                              nonce_buffer, sizeof nonce_buffer);
      n = length > 20? 20 : length;
      memcpy (p, nonce_buffer, n);
    }

  /* Release the nonce buffer lock. */
  err = ath_mutex_unlock (&nonce_buffer_lock);
  if (err)
    log_fatal ("failed to release the nonce buffer lock: %s\n",
               strerror (err));
}
示例#4
0
/* Public function to fill the buffer with LENGTH bytes of
   cryptographically strong random bytes.  Level GCRY_WEAK_RANDOM is
   not very strong, GCRY_STRONG_RANDOM is strong enough for most
   usage, GCRY_VERY_STRONG_RANDOM is good for key generation stuff but
   may be very slow.  */
void
gcry_randomize (void *buffer, size_t length, enum gcry_random_level level)
{
  do_randomize (buffer, length, level);
}
示例#5
0
文件: main.c 项目: wgc1212/pimd
int main(int argc, char *argv[])
{
    int foreground = 0, do_syslog = 1;
    fd_set fds;
    int nfds, fd, n = -1, i, ch;
    struct sigaction sa;
    struct option long_options[] = {
	{ "config",        1, 0, 'f' },
	{ "no-fallback",   0, 0, 500 },
	{ "disable-vifs",  0, 0, 'N' },
	{ "foreground",    0, 0, 'n' },
	{ "help",          0, 0, 'h' },
	{ "ident",         1, 0, 'I' },
	{ "loglevel",      1, 0, 'l' },
	{ "pidfile",       1, 0, 'P' },
	{ "syslog",        0, 0, 's' },
	{ "table-id",      1, 0, 't' },
	{ "version",       0, 0, 'v' },
	{ NULL, 0, 0, 0 }
    };

    snprintf(versionstring, sizeof (versionstring), "pimd version %s", PACKAGE_VERSION);

    prognm = ident = progname(argv[0]);
    while ((ch = getopt_long(argc, argv, "d:f:hI:l:nNP:rst:v", long_options, NULL)) != EOF) {
	const char *errstr;

	switch (ch) {
	    case 'd':
		{
		    char *p,*q;
		    size_t i, len;
		    struct debugname *d;

		    debug = 0;
		    p = optarg;
		    q = NULL;
		    while (p) {
			q = strchr(p, ',');
			if (q)
			    *q++ = '\0';
			len = strlen(p);
			for (i = 0, d = debugnames; i < ARRAY_LEN(debugnames); i++, d++) {
			    if (len >= d->nchars && strncmp(d->name, p, len) == 0)
				break;
			}

			if (i == ARRAY_LEN(debugnames))
			    return usage(1);

			debug |= d->level;
			p = q;
		    }
		}
		break;

	    case 'f':
		config_file = optarg;
		break;

	    case 500:
		no_fallback = 1;
		break;

	    case 'h':
		return usage(0);

	    case 'I':	/* --ident=NAME */
		ident = optarg;
		break;

	    case 'l':
		loglevel = loglvl(optarg);
		if (-1 == loglevel)
		    return usage(1);
		break;

	    case 'n':
		do_syslog--;
		foreground = 1;
		break;

	    case 'N':
		do_vifs = 0;
		break;

	    case 'P':	/* --pidfile=NAME */
		pid_file = strdup(optarg);
		break;

	    case 'r':
		retry_forever++;
		break;

	    case 's':
		do_syslog++;
		break;

	    case 't':
		mrt_table_id = strtonum(optarg, 0, 999999999, &errstr);
		if (errstr) {
		    fprintf(stderr, "Table ID %s!\n", errstr);
		    return usage(1);
		}
		break;

	    case 'v':
		printf("%s\n", versionstring);
		return 0;

	    default:
		return usage(1);
	}
    }

    argc -= optind;
    if (argc > 0)
	return usage(1);

    if (geteuid() != 0)
	errx(1, "Need root privileges to start.");

    compose_paths();
    setlinebuf(stderr);

    if (debug != 0) {
	struct debugname *d;
	char c;
	int tmpd = debug;

	fprintf(stderr, "debug level 0x%lx ", debug);
	c = '(';
	for (d = debugnames; d < debugnames + ARRAY_LEN(debugnames); d++) {
	    if ((tmpd & d->level) == d->level) {
		tmpd &= ~d->level;
		fprintf(stderr, "%c%s", c, d->name);
		c = ',';
	    }
	}
	fprintf(stderr, ")\n");
    }

    if (!debug && !foreground) {
	/* Detach from the terminal */
	haveterminal = 0;
	if (fork())
	    exit(0);

	close(STDIN_FILENO);
	close(STDOUT_FILENO);
	close(STDERR_FILENO);

	fd = open("/dev/null", O_RDWR, 0);
	if (fd >= 0) {
	    dup2(fd, STDIN_FILENO);
	    dup2(fd, STDOUT_FILENO);
	    dup2(fd, STDERR_FILENO);
	    close(fd);
	}
#ifdef SYSV
	setpgrp();
#else
#ifdef TIOCNOTTY
	fd = open("/dev/tty", 2);
	if (fd >= 0) {
	    (void)ioctl(fd, TIOCNOTTY, (char *)0);
	    close(fd);
	}
#else
	if (setsid() < 0)
	    perror("setsid");
#endif /* TIOCNOTTY */
#endif /* SYSV */
    } /* End of child process code */

    /*
     * Create directory for runtime files
     */
    if (-1 == mkdir(_PATH_PIMD_RUNDIR, 0755) && errno != EEXIST)
	err(1, "Failed creating %s directory for runtime files", _PATH_PIMD_RUNDIR);

    /*
     * Setup logging
     */
    log_init(haveterminal && do_syslog > 0);
    logit(LOG_NOTICE, 0, "%s starting ...", versionstring);

    do_randomize();

    callout_init();
    init_igmp();
    init_pim();
    init_routesock(); /* Both for Linux netlink and BSD routing socket */
    init_pim_mrt();
    init_timers();
    ipc_init();

    /* Start up the log rate-limiter */
    resetlogging(NULL);

    /* TODO: check the kernel DVMRP/MROUTED/PIM support version */

    init_vifs();
    init_rp_and_bsr();   /* Must be after init_vifs() */
    add_static_rp();	 /* Must be after init_vifs() */
#ifdef RSRR
    rsrr_init();
#endif /* RSRR */

    sa.sa_handler = handle_signals;
    sa.sa_flags = 0;	/* Interrupt system calls */
    sigemptyset(&sa.sa_mask);
    sigaction(SIGALRM, &sa, NULL);
    sigaction(SIGHUP, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGUSR1, &sa, NULL);
    sigaction(SIGUSR2, &sa, NULL);

    IF_DEBUG(DEBUG_IF)
	dump_vifs(stderr);
    IF_DEBUG(DEBUG_PIM_MRT)
	dump_pim_mrt(stderr);

    /* schedule first timer interrupt */
    timer_setTimer(TIMER_INTERVAL, timer, NULL);

    if (pidfile(pid_file))
	warn("Cannot create pidfile");

    /*
     * Main receive loop.
     */
    while (1) {
	if (check_signals())
	    break;

	FD_ZERO(&fds);
	for (i = 0, nfds = 0; i < nhandlers; i++) {
	    FD_SET(ihandlers[i].fd, &fds);
	    if (ihandlers[i].fd >= nfds)
		nfds = ihandlers[i].fd + 1;
	}

	n = select(nfds, &fds, NULL, NULL, timeout(n));
	if (n < 0) {
	    if (errno != EINTR) /* SIGALRM is expected */
		logit(LOG_WARNING, errno, "select failed");
	    continue;
	}

	for (i = 0; n > 0 && i < nhandlers; i++) {
	    if (FD_ISSET(ihandlers[i].fd, &fds))
		ihandlers[i].func(ihandlers[i].fd);
	}
    }

    logit(LOG_NOTICE, 0, "%s exiting.", versionstring);
    cleanup();
    exit(0);
}
示例#6
0
文件: main.c 项目: tzuryby/pimd
int main(int argc, char *argv[])
{	
    int dummy, dummysigalrm, foreground = 0;
    struct timeval tv, difftime, curtime, lasttime, *timeout;
    fd_set rfds, readers;
    int nfds, n, i, secs, ch;
    struct sigaction sa;
    time_t boottime;
    struct option long_options[] = {
	{"config", 1, 0, 'c'},
	{"debug", 2, 0, 'd'},
	{"foreground", 0, 0, 'f'},
	{"disable-vifs", 0, 0, 'N'},
	{"help", 0, 0, 'h'},
	{"version", 0, 0, 'v'},
	{"quit-daemon", 0, 0, 'q'},
	{"reload-config", 0, 0, 'l'},
	{"show-routes", 0, 0, 'r'},
	/* {"show-cache", 0, 0, 'i'}, */
	/* {"show-debug", 0, 0, 'p'}, */
	{0, 0, 0, 0}
    };
    
    snprintf(versionstring, sizeof (versionstring), "pimd version %s", todaysversion);

    while ((ch = getopt_long (argc, argv, "c:d::fhlNP::vqr", long_options, NULL)) != EOF) {
	switch (ch) {
	    case 'c':
		configfilename = optarg;
		break;

	    case 'd':
		if (!optarg) {
		    debug = DEBUG_DEFAULT;
		} else {
		    char *p,*q;
		    size_t i, len;
		    struct debugname *d;

		    debug = 0;
		    p = optarg; q = NULL;
		    while (p) {
			q = strchr(p, ',');
			if (q)
			    *q++ = '\0';
			len = strlen(p);
			for (i = 0, d = debugnames; i < ARRAY_LEN(debugnames); i++, d++)
			    if (len >= d->nchars && strncmp(d->name, p, len) == 0)
				break;

			if (i == ARRAY_LEN(debugnames))
			    return usage();

			debug |= d->level;
			p = q;
		    }
		}
		break;

	    case 'f':
		foreground = 1;
		break;

	    case 'h':
		return usage();

	    case 'l':
		killshow(SIGHUP, NULL);
		return 0;

	    case 'N':
		disable_all_by_default = 1;
		break;

	    case 'P':
#ifdef SNMP
		if (!optarg)
		    dest_port = DEFAULT_PORT;
		else {
		    dest_port = strtonum(optarg, 1, 65535, &errstr);
		    if (errstr) {
			warnx("destination port %s", errstr);
			dest_port = DEFAULT_PORT;
		    }
		}
#else
		warnx("SNMP support missing, please feel free to submit a patch.");
#endif
		break;

	    case 'v':
		printf("%s\n", versionstring);
		return 0;

	    case 'q':
		killshow(SIGTERM, NULL);
		return 0;

	    case 'r':
		killshow(SIGUSR1, _PATH_PIMD_DUMP);
		return 0;
#if 0 /* XXX: TODO */
	    case 'i':
		killshow(SIGUSR2, _PATH_PIMD_CACHE);
		return 0;

	    case 'p':
		killshow(SIGQUIT, NULL);
		return 0;
#endif
	    default:
		return usage();
	}
    }

    argc -= optind;
    argv += optind;

    if (argc > 0) {
	return usage();
    }

    if (geteuid() != 0) {
	fprintf(stderr, "%s: must be root\n", __progname);
	exit(1);
    }
    setlinebuf(stderr);

    if (debug != 0) {
	struct debugname *d;
	char c;
	int tmpd = debug;

	fprintf(stderr, "debug level 0x%lx ", debug);
	c = '(';
	for (d = debugnames; d < debugnames + ARRAY_LEN(debugnames); d++) {
	    if ((tmpd & d->level) == d->level) {
		tmpd &= ~d->level;
		fprintf(stderr, "%c%s", c, d->name);
		c = ',';
	    }
	}
	fprintf(stderr, ")\n");
    }
    
    /*
     * Create directory for runtime files
     */
    mkdir(_PATH_PIMD_RUNDIR, 0755);

    /*
     * Setup logging
     */
#ifdef LOG_DAEMON
    (void)openlog("pimd", LOG_PID, LOG_DAEMON);
    (void)setlogmask(LOG_UPTO(LOG_NOTICE));
#else
    (void)openlog("pimd", LOG_PID);
#endif /* LOG_DAEMON */

    logit(LOG_DEBUG, 0, "%s starting", versionstring);

    do_randomize();
    time(&boottime);
    
    /* Start up the log rate-limiter */
    resetlogging(NULL);

    callout_init();
    init_igmp();
    init_pim();
#ifdef HAVE_ROUTING_SOCKETS
    init_routesock();
#endif /* HAVE_ROUTING_SOCKETS */
    init_pim_mrt();
    init_timers();
    
    /* TODO: check the kernel DVMRP/MROUTED/PIM support version */
    
#ifdef SNMP
    if (i = snmp_init())
	return i;
#endif /* SNMP */
    init_vifs();
    init_rp_and_bsr();   /* Must be after init_vifs() */
    
#ifdef RSRR
    rsrr_init();
#endif /* RSRR */
    
    sa.sa_handler = handler;
    sa.sa_flags = 0;	/* Interrupt system calls */
    sigemptyset(&sa.sa_mask);
    sigaction(SIGALRM, &sa, NULL);
    sigaction(SIGHUP, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGUSR1, &sa, NULL);
    sigaction(SIGUSR2, &sa, NULL);
    
    FD_ZERO(&readers);
    FD_SET(igmp_socket, &readers);
    nfds = igmp_socket + 1;
    for (i = 0; i < nhandlers; i++) {
	FD_SET(ihandlers[i].fd, &readers);
	if (ihandlers[i].fd >= nfds)
	    nfds = ihandlers[i].fd + 1;
    }
    
    IF_DEBUG(DEBUG_IF)
	dump_vifs(stderr);
    IF_DEBUG(DEBUG_PIM_MRT)
	dump_pim_mrt(stderr);
    
    /* schedule first timer interrupt */
    timer_setTimer(TIMER_INTERVAL, timer, NULL);
    
    if (!debug && !foreground) {
	/* Detach from the terminal */
	haveterminal = 0;
	if (fork())
	    exit(0);
	(void)close(0);
	(void)close(1);
	(void)close(2);
	(void)open("/", 0);
	(void)dup2(0, 1);
	(void)dup2(0, 2);
#ifdef SYSV
	(void)setpgrp();
#else 
#ifdef TIOCNOTTY
	n = open("/dev/tty", 2);
	if (n >= 0) {
	    (void)ioctl(n, TIOCNOTTY, (char *)0);
	    (void)close(n);
	}
#else
	if (setsid() < 0)
	    perror("setsid");
#endif /* TIOCNOTTY */
#endif /* SYSV */
    } /* End of child process code */
    
    if (pidfile(NULL)) {
	warn("Cannot create pidfile");
    }

    /*
     * Main receive loop.
     */
    dummy = 0;
    dummysigalrm = SIGALRM;
    difftime.tv_usec = 0;
    gettimeofday(&curtime, NULL);
    lasttime = curtime;
    while (1) {
	memcpy(&rfds, &readers, sizeof(rfds));
	secs = timer_nextTimer();
	if (secs == -1)
	    timeout = NULL;
	else {
	    timeout = &tv;
	    timeout->tv_sec = secs;
	   timeout->tv_usec = 0;
        }

        if (boottime) {
           time_t n;

           time(&n);
           if (n > boottime + 15) {
              struct rp_hold *rph = g_rp_hold;

              while(rph) {
                 add_rp_grp_entry(&cand_rp_list, &grp_mask_list,
                                  rph->address, 1, (u_int16)0xffffff, rph->group, rph->mask,
                                  curr_bsr_hash_mask, curr_bsr_fragment_tag);
                 rph = rph->next;
              }
              boottime = 0;
           }
        }
	
	if (sighandled) {
	    if (sighandled & GOT_SIGINT) {
		sighandled &= ~GOT_SIGINT;
		break;
	    }
	    if (sighandled & GOT_SIGHUP) {
		sighandled &= ~GOT_SIGHUP;
		restart(SIGHUP);
		
		/* reconstruct readers and nfds */
		FD_ZERO(&readers);
		FD_SET(igmp_socket, &readers);
		nfds = igmp_socket + 1;
		for (i = 0; i < nhandlers; i++) {
		    FD_SET(ihandlers[i].fd, &readers);
		    if (ihandlers[i].fd >= nfds)
			nfds = ihandlers[i].fd + 1;
		}
		memcpy(&rfds, &readers, sizeof(rfds));
	    }
	    if (sighandled & GOT_SIGUSR1) {
		sighandled &= ~GOT_SIGUSR1;
		fdump(SIGUSR1);
	    }
	    if (sighandled & GOT_SIGUSR2) {
		sighandled &= ~GOT_SIGUSR2;
		cdump(SIGUSR2);
	    }
	    if (sighandled & GOT_SIGALRM) {
		sighandled &= ~GOT_SIGALRM;
		timer(&dummysigalrm);
	    }
	}
	if ((n = select(nfds, &rfds, NULL, NULL, timeout)) < 0) {
	    if (errno != EINTR) /* SIGALRM is expected */
		logit(LOG_WARNING, errno, "select failed");
	    continue;
	}
	if (n > 0) {
	    /* TODO: shall check first igmp_socket for better performance? */
	    for (i = 0; i < nhandlers; i++) {
		if (FD_ISSET(ihandlers[i].fd, &rfds)) {
		    (*ihandlers[i].func)(ihandlers[i].fd, &rfds);
		}
	    }
	}
    
	/*
	 * Handle timeout queue.
	 *
	 * If select + packet processing took more than 1 second,
	 * or if there is a timeout pending, age the timeout queue.
	 *
	 * If not, collect usec in difftime to make sure that the
	 * time doesn't drift too badly.
	 *
	 * If the timeout handlers took more than 1 second,
	 * age the timeout queue again.  XXX This introduces the
	 * potential for infinite loops!
	 */
	do {
	    /*
	     * If the select timed out, then there's no other
	     * activity to account for and we don't need to
	     * call gettimeofday.
	     */
	    if (n == 0) {
		curtime.tv_sec = lasttime.tv_sec + secs;
		curtime.tv_usec = lasttime.tv_usec;
		n = -1;	/* don't do this next time through the loop */
	    } else
		gettimeofday(&curtime, NULL);
	    difftime.tv_sec = curtime.tv_sec - lasttime.tv_sec;
	    difftime.tv_usec += curtime.tv_usec - lasttime.tv_usec;
	    while (difftime.tv_usec >= 1000000) {
		difftime.tv_sec++;
		difftime.tv_usec -= 1000000;
	    }
	    if (difftime.tv_usec < 0) {
		difftime.tv_sec--;
		difftime.tv_usec += 1000000;
	    }
	    lasttime = curtime;
	    if (secs == 0 || difftime.tv_sec > 0)
		age_callout_queue(difftime.tv_sec);
	    secs = -1;
	} while (difftime.tv_sec > 0);
    } /* Main loop */

    logit(LOG_NOTICE, 0, "%s exiting", versionstring);
    cleanup();
    exit(0);
}