示例#1
0
文件: eth.c 项目: 01hyang/u-boot
int board_eth_init(bd_t *bis)
{
#ifdef CONFIG_FMAN_ENET
	struct fsl_pq_mdio_info dtsec_mdio_info;
	unsigned int i;

	printf("Initializing Fman\n");


	/* Register the real 1G MDIO bus */
	dtsec_mdio_info.regs =
		(struct tsec_mii_mng *)CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR;
	dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME;

	fsl_pq_mdio_init(bis, &dtsec_mdio_info);


	fm_info_set_phy_address(FIRST_PORT, FIRST_PORT_ADDR);
	fm_info_set_mdio(FIRST_PORT,
			miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME));
	fm_info_set_phy_address(SECOND_PORT, SECOND_PORT_ADDR);
	fm_info_set_mdio(SECOND_PORT,
			miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME));

	/* Never disable DTSEC1 - it controls MDIO */
	for (i = FM1_DTSEC2; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
		if (!IS_VALID_PORT(i))
			fm_disable_port(i);
	}

#ifdef CONFIG_PPC_P5040
	for (i = FM2_DTSEC2; i < FM2_DTSEC1 + CONFIG_SYS_NUM_FM2_DTSEC; i++) {
		if (!IS_VALID_PORT(i))
			fm_disable_port(i);
	}
#endif

	cpu_eth_init(bis);

	cyrus_phy_tuning(FIRST_PORT_ADDR);
	cyrus_phy_tuning(SECOND_PORT_ADDR);
#endif

	return pci_eth_init(bis);
}
示例#2
0
void Dio_WritePort(Dio_PortType portId, Dio_PortLevelType level)
{
    VALIDATE( DioGlobal.InitRun, DIO_READCHANNELGROUP_ID, DIO_E_UNINIT );
    /** @req SWS_Dio_00074 */
    VALIDATE( IS_VALID_PORT(portId), DIO_WRITEPORT_ID, DIO_E_PARAM_INVALID_PORT_ID );

	GPIO_Write(GPIO_ports[portId], level);

	return;
}
示例#3
0
Dio_PortLevelType Dio_ReadPort(Dio_PortType portId)
{
    Dio_PortLevelType level = 0;
    VALIDATE_RV( DioGlobal.InitRun, DIO_READPORT_ID, DIO_E_UNINIT, (Dio_PortLevelType)0 );
    /** @req SWS_Dio_00074 */
    VALIDATE_RV( IS_VALID_PORT(portId), DIO_READPORT_ID, DIO_E_PARAM_INVALID_PORT_ID, (Dio_PortLevelType)0 );

	level = GPIO_ReadInputData(GPIO_ports[portId]);

	return level;
}
示例#4
0
文件: main.c 项目: bjhockley/rtpproxy
static void
init_config(struct cfg *cf, int argc, char **argv)
{
    int ch, i;
    char *bh[2], *bh6[2], *cp, *tp[2];
    const char *errmsg;
    struct passwd *pp;
    struct group *gp;
    double x, y;

    bh[0] = bh[1] = bh6[0] = bh6[1] = NULL;

    cf->stable->port_min = PORT_MIN;
    cf->stable->port_max = PORT_MAX;
    cf->stable->port_ctl = 0;

    cf->stable->advaddr[0] = NULL;
    cf->stable->advaddr[1] = NULL;

    cf->stable->max_ttl = SESSION_TIMEOUT;
    cf->stable->tos = TOS;
    cf->stable->rrtcp = 1;
    cf->stable->ttl_mode = TTL_UNIFIED;
    cf->stable->log_level = -1;
    cf->stable->log_facility = -1;
    cf->stable->sched_offset = 0.0;
    cf->stable->sched_hz = rtpp_get_sched_hz();
    cf->stable->sched_policy = SCHED_OTHER;
    cf->stable->target_pfreq = MIN(POLL_RATE, cf->stable->sched_hz);
#if defined(RTPP_DEBUG)
    printf("target_pfreq = %f\n", cf->stable->target_pfreq);
#endif
    cf->stable->slowshutdown = 0;

    cf->timeout_handler = rtpp_th_init();
    if (cf->timeout_handler == NULL)
        err(1, "rtpp_th_init");

    pthread_mutex_init(&cf->glock, NULL);
    pthread_mutex_init(&cf->sessinfo.lock, NULL);
    pthread_mutex_init(&cf->bindaddr_lock, NULL);

    cf->stable->nofile_limit = malloc(sizeof(*cf->stable->nofile_limit));
    if (cf->stable->nofile_limit == NULL)
        err(1, "malloc");
    if (getrlimit(RLIMIT_NOFILE, cf->stable->nofile_limit) != 0)
	err(1, "getrlimit");

    while ((ch = getopt(argc, argv, "vf2Rl:6:s:S:t:r:p:T:L:m:M:u:Fin:Pad:VN:c:A:")) != -1)
	switch (ch) {
        case 'c':
            if (strcmp(optarg, "fifo") == 0) {
                 cf->stable->sched_policy = SCHED_FIFO;
                 break;
            }
            if (strcmp(optarg, "rr") == 0) {
                 cf->stable->sched_policy = SCHED_RR;
                 break;
            }
            errx(1, "%s: unknown scheduling policy", optarg);
            break;

        case 'N':
	    if (strcmp(optarg, "random") == 0) {
                x = getdtime() * 1000000.0;
                srand48((long)x);
                cf->stable->sched_offset = drand48();
            } else {
                tp[0] = optarg;
                tp[1] = strchr(tp[0], '/');
       	        if (tp[1] == NULL) {
                    errx(1, "%s: -N should be in the format X/Y", optarg);
                }
                *tp[1] = '\0';
                tp[1]++;
                x = (double)strtol(tp[0], &tp[0], 10);
                y = (double)strtol(tp[1], &tp[1], 10);
                cf->stable->sched_offset = x / y;
            }
            x = (double)cf->stable->sched_hz / cf->stable->target_pfreq;
            cf->stable->sched_offset = trunc(x * cf->stable->sched_offset) / x;
            cf->stable->sched_offset /= cf->stable->target_pfreq;
            warnx("sched_offset = %f",  cf->stable->sched_offset);
            break;

	case 'f':
	    cf->stable->nodaemon = 1;
	    break;

	case 'l':
	    bh[0] = optarg;
	    bh[1] = strchr(bh[0], '/');
	    if (bh[1] != NULL) {
		*bh[1] = '\0';
		bh[1]++;
		cf->stable->bmode = 1;
	    }
	    break;

	case '6':
	    bh6[0] = optarg;
	    bh6[1] = strchr(bh6[0], '/');
	    if (bh6[1] != NULL) {
		*bh6[1] = '\0';
		bh6[1]++;
		cf->stable->bmode = 1;
	    }
	    break;

    case 'A':
        if (*optarg == '\0') {
            errx(1, "first advertised address is invalid");
        }
        cf->stable->advaddr[0] = optarg;
        cp = strchr(optarg, '/');
        if (cp != NULL) {
            *cp = '\0';
            cp++;
            if (*cp == '\0') {
                errx(1, "second advertised address is invalid");
            }
        }
        cf->stable->advaddr[1] = cp;
        break;

	case 's':
	    if (strncmp("udp:", optarg, 4) == 0) {
		cf->stable->umode = 1;
		optarg += 4;
	    } else if (strncmp("udp6:", optarg, 5) == 0) {
		cf->stable->umode = 6;
		optarg += 5;
	    } else if (strncmp("unix:", optarg, 5) == 0) {
		cf->stable->umode = 0;
		optarg += 5;
	    }
	    cmd_sock = optarg;
	    break;

	case 't':
	    cf->stable->tos = atoi(optarg);
	    if (cf->stable->tos > 255)
		errx(1, "%d: TOS is too large", cf->stable->tos);
	    break;

	case '2':
	    cf->stable->dmode = 1;
	    break;

	case 'v':
	    printf("Basic version: %d\n", CPROTOVER);
	    for (i = 1; proto_caps[i].pc_id != NULL; ++i) {
		printf("Extension %s: %s\n", proto_caps[i].pc_id,
		    proto_caps[i].pc_description);
	    }
	    exit(0);
	    break;

	case 'r':
	    cf->stable->rdir = optarg;
	    break;

	case 'S':
	    cf->stable->sdir = optarg;
	    break;

	case 'R':
	    cf->stable->rrtcp = 0;
	    break;

	case 'p':
	    pid_file = optarg;
	    break;

	case 'T':
	    cf->stable->max_ttl = atoi(optarg);
	    break;

	case 'L':
	    cf->stable->nofile_limit->rlim_cur = cf->stable->nofile_limit->rlim_max = atoi(optarg);
	    if (setrlimit(RLIMIT_NOFILE, cf->stable->nofile_limit) != 0)
		err(1, "setrlimit");
	    if (getrlimit(RLIMIT_NOFILE, cf->stable->nofile_limit) != 0)
		err(1, "getrlimit");
	    if (cf->stable->nofile_limit->rlim_max < atoi(optarg))
		warnx("limit allocated by setrlimit (%d) is less than "
		  "requested (%d)", (int) cf->stable->nofile_limit->rlim_max,
		  atoi(optarg));
	    break;

	case 'm':
	    cf->stable->port_min = atoi(optarg);
	    break;

	case 'M':
	    cf->stable->port_max = atoi(optarg);
	    break;

	case 'u':
	    cf->stable->run_uname = optarg;
	    cp = strchr(optarg, ':');
	    if (cp != NULL) {
		if (cp == optarg)
		    cf->stable->run_uname = NULL;
		cp[0] = '\0';
		cp++;
	    }
	    cf->stable->run_gname = cp;
	    cf->stable->run_uid = -1;
	    cf->stable->run_gid = -1;
	    if (cf->stable->run_uname != NULL) {
		pp = getpwnam(cf->stable->run_uname);
		if (pp == NULL)
		    err(1, "can't find ID for the user: %s", cf->stable->run_uname);
		cf->stable->run_uid = pp->pw_uid;
		if (cf->stable->run_gname == NULL)
		    cf->stable->run_gid = pp->pw_gid;
	    }
	    if (cf->stable->run_gname != NULL) {
		gp = getgrnam(cf->stable->run_gname);
		if (gp == NULL)
		    err(1, "can't find ID for the group: %s", cf->stable->run_gname);
		cf->stable->run_gid = gp->gr_gid;
	    }
	    break;

	case 'F':
	    cf->stable->no_check = 1;
	    break;

	case 'i':
	    cf->stable->ttl_mode = TTL_INDEPENDENT;
	    break;

	case 'n':
	    if(strncmp("unix:", optarg, 5) == 0)
		optarg += 5;
	    if(strlen(optarg) == 0)
		errx(1, "timeout notification socket name too short");
            if (rtpp_th_set_sn(cf->timeout_handler, optarg, NULL) == NULL) {
		err(1, "can't allocate memory");
            }
	    break;

	case 'P':
	    cf->stable->record_pcap = 1;
	    break;

	case 'a':
	    cf->stable->record_all = 1;
	    break;

	case 'd':
	    cp = strchr(optarg, ':');
	    if (cp != NULL) {
		cf->stable->log_facility = rtpp_log_str2fac(cp + 1);
		if (cf->stable->log_facility == -1)
		    errx(1, "%s: invalid log facility", cp + 1);
		*cp = '\0';
	    }
	    cf->stable->log_level = rtpp_log_str2lvl(optarg);
	    if (cf->stable->log_level == -1)
		errx(1, "%s: invalid log level", optarg);
	    break;

	case 'V':
	    printf("%s\n", RTPP_SW_VERSION);
	    exit(0);
	    break;

	case '?':
	default:
	    usage();
	}
    if (cf->stable->rdir == NULL && cf->stable->sdir != NULL)
	errx(1, "-S switch requires -r switch");

    if (cf->stable->no_check == 0 && getuid() == 0 && cf->stable->run_uname == NULL) {
	if (cf->stable->umode != 0) {
	    errx(1, "running this program as superuser in a remote control "
	      "mode is strongly not recommended, as it poses serious security "
	      "threat to your system. Use -u option to run as an unprivileged "
	      "user or -F is you want to run as a superuser anyway.");
	} else {
	    warnx("WARNING!!! Running this program as superuser is strongly "
	      "not recommended, as it may pose serious security threat to "
	      "your system. Use -u option to run as an unprivileged user "
	      "or -F to surpress this warning.");
	}
    }

    /* make sure that port_min and port_max are even */
    if ((cf->stable->port_min % 2) != 0)
	cf->stable->port_min++;
    if ((cf->stable->port_max % 2) != 0) {
	cf->stable->port_max--;
    } else {
	/*
	 * If port_max is already even then there is no
	 * "room" for the RTCP port, go back by two ports.
	 */
	cf->stable->port_max -= 2;
    }

    if (!IS_VALID_PORT(cf->stable->port_min))
	errx(1, "invalid value of the port_min argument, "
	  "not in the range 1-65535");
    if (!IS_VALID_PORT(cf->stable->port_max))
	errx(1, "invalid value of the port_max argument, "
	  "not in the range 1-65535");
    if (cf->stable->port_min > cf->stable->port_max)
	errx(1, "port_min should be less than port_max");

    cf->sessinfo.sessions = malloc((sizeof cf->sessinfo.sessions[0]) *
      (((cf->stable->port_max - cf->stable->port_min + 1)) + 1));
    cf->rtp_servers =  malloc((sizeof cf->rtp_servers[0]) *
      (((cf->stable->port_max - cf->stable->port_min + 1) * 2) + 1));
    cf->sessinfo.pfds_rtp = malloc((sizeof cf->sessinfo.pfds_rtp[0]) *
      (((cf->stable->port_max - cf->stable->port_min + 1)) + 1));
    cf->sessinfo.pfds_rtcp = malloc((sizeof cf->sessinfo.pfds_rtcp[0]) *
      (((cf->stable->port_max - cf->stable->port_min + 1)) + 1));

    if (bh[0] == NULL && bh[1] == NULL && bh6[0] == NULL && bh6[1] == NULL) {
	bh[0] = "*";
    }

    for (i = 0; i < 2; i++) {
	if (bh[i] != NULL && *bh[i] == '\0')
	    bh[i] = NULL;
	if (bh6[i] != NULL && *bh6[i] == '\0')
	    bh6[i] = NULL;
    }

    i = ((bh[0] == NULL) ? 0 : 1) + ((bh[1] == NULL) ? 0 : 1) +
      ((bh6[0] == NULL) ? 0 : 1) + ((bh6[1] == NULL) ? 0 : 1);
    if (cf->stable->bmode != 0) {
	if (bh[0] != NULL && bh6[0] != NULL)
	    errx(1, "either IPv4 or IPv6 should be configured for external "
	      "interface in bridging mode, not both");
	if (bh[1] != NULL && bh6[1] != NULL)
	    errx(1, "either IPv4 or IPv6 should be configured for internal "
	      "interface in bridging mode, not both");
    if (cf->stable->advaddr[0] != NULL && cf->stable->advaddr[1] == NULL)
        errx(1, "two advertised addresses are required for internal "
          "and external interfaces in bridging mode");
	if (i != 2)
	    errx(1, "incomplete configuration of the bridging mode - exactly "
	      "2 listen addresses required, %d provided", i);
    } else if (i != 1) {
	errx(1, "exactly 1 listen addresses required, %d provided", i);
    }

    for (i = 0; i < 2; i++) {
	cf->stable->bindaddr[i] = NULL;
	if (bh[i] != NULL) {
	    cf->stable->bindaddr[i] = host2bindaddr(cf, bh[i], AF_INET, &errmsg);
	    if (cf->stable->bindaddr[i] == NULL)
		errx(1, "host2bindaddr: %s", errmsg);
	    continue;
	}
	if (bh6[i] != NULL) {
	    cf->stable->bindaddr[i] = host2bindaddr(cf, bh6[i], AF_INET6, &errmsg);
	    if (cf->stable->bindaddr[i] == NULL)
		errx(1, "host2bindaddr: %s", errmsg);
	    continue;
	}
    }
    if (cf->stable->bindaddr[0] == NULL) {
	cf->stable->bindaddr[0] = cf->stable->bindaddr[1];
	cf->stable->bindaddr[1] = NULL;
    }
}
示例#5
0
static void
init_config(struct cfg *cf, int argc, char **argv)
{
    int ch, i;
    char *bh[2], *bh6[2], *cp;
    const char *errmsg;
    struct passwd *pp;
    struct group *gp;

    bh[0] = bh[1] = bh6[0] = bh6[1] = NULL;

    cf->stable.port_min = PORT_MIN;
    cf->stable.port_max = PORT_MAX;

    cf->stable.max_ttl = SESSION_TIMEOUT;
    cf->stable.tos = TOS;
    cf->stable.rrtcp = 1;
    cf->stable.ttl_mode = TTL_UNIFIED;
    cf->stable.log_level = -1;
    cf->stable.log_facility = -1;

    pthread_mutex_init(&cf->glock, NULL);
    pthread_mutex_init(&cf->sessinfo.lock, NULL);
    pthread_mutex_init(&cf->bindaddr_lock, NULL);

    if (getrlimit(RLIMIT_NOFILE, &(cf->stable.nofile_limit)) != 0)
	err(1, "getrlimit");

    while ((ch = getopt(argc, argv, "vf2Rl:6:s:S:t:r:p:T:L:m:M:u:Fin:Pad:")) != -1)
	switch (ch) {
	case 'f':
	    cf->stable.nodaemon = 1;
	    break;

	case 'l':
	    bh[0] = optarg;
	    bh[1] = strchr(bh[0], '/');
	    if (bh[1] != NULL) {
		*bh[1] = '\0';
		bh[1]++;
		cf->stable.bmode = 1;
	    }
	    break;

	case '6':
	    bh6[0] = optarg;
	    bh6[1] = strchr(bh6[0], '/');
	    if (bh6[1] != NULL) {
		*bh6[1] = '\0';
		bh6[1]++;
		cf->stable.bmode = 1;
	    }
	    break;

	case 's':
	    if (strncmp("udp:", optarg, 4) == 0) {
		cf->stable.umode = 1;
		optarg += 4;
	    } else if (strncmp("udp6:", optarg, 5) == 0) {
		cf->stable.umode = 6;
		optarg += 5;
	    } else if (strncmp("unix:", optarg, 5) == 0) {
		cf->stable.umode = 0;
		optarg += 5;
	    }
	    cmd_sock = optarg;
	    break;

	case 't':
	    cf->stable.tos = atoi(optarg);
	    if (cf->stable.tos > 255)
		errx(1, "%d: TOS is too large", cf->stable.tos);
	    break;

	case '2':
	    cf->stable.dmode = 1;
	    break;

	case 'v':
	    printf("Basic version: %d\n", CPROTOVER);
	    for (i = 1; proto_caps[i].pc_id != NULL; ++i) {
		printf("Extension %s: %s\n", proto_caps[i].pc_id,
		    proto_caps[i].pc_description);
	    }
	    exit(0);
	    break;

	case 'r':
	    cf->stable.rdir = optarg;
	    break;

	case 'S':
	    cf->stable.sdir = optarg;
	    break;

	case 'R':
	    cf->stable.rrtcp = 0;
	    break;

	case 'p':
	    pid_file = optarg;
	    break;

	case 'T':
	    cf->stable.max_ttl = atoi(optarg);
	    break;

	case 'L':
	    cf->stable.nofile_limit.rlim_cur = cf->stable.nofile_limit.rlim_max = atoi(optarg);
	    if (setrlimit(RLIMIT_NOFILE, &(cf->stable.nofile_limit)) != 0)
		err(1, "setrlimit");
	    if (getrlimit(RLIMIT_NOFILE, &(cf->stable.nofile_limit)) != 0)
		err(1, "getrlimit");
	    if (cf->stable.nofile_limit.rlim_max < atoi(optarg))
		warnx("limit allocated by setrlimit (%d) is less than "
		  "requested (%d)", (int) cf->stable.nofile_limit.rlim_max,
		  atoi(optarg));
	    break;

	case 'm':
	    cf->stable.port_min = atoi(optarg);
	    break;

	case 'M':
	    cf->stable.port_max = atoi(optarg);
	    break;

	case 'u':
	    cf->stable.run_uname = optarg;
	    cp = strchr(optarg, ':');
	    if (cp != NULL) {
		if (cp == optarg)
		    cf->stable.run_uname = NULL;
		cp[0] = '\0';
		cp++;
	    }
	    cf->stable.run_gname = cp;
	    cf->stable.run_uid = -1;
	    cf->stable.run_gid = -1;
	    if (cf->stable.run_uname != NULL) {
		pp = getpwnam(cf->stable.run_uname);
		if (pp == NULL)
		    err(1, "can't find ID for the user: %s", cf->stable.run_uname);
		cf->stable.run_uid = pp->pw_uid;
		if (cf->stable.run_gname == NULL)
		    cf->stable.run_gid = pp->pw_gid;
	    }
	    if (cf->stable.run_gname != NULL) {
		gp = getgrnam(cf->stable.run_gname);
		if (gp == NULL)
		    err(1, "can't find ID for the group: %s", cf->stable.run_gname);
		cf->stable.run_gid = gp->gr_gid;
	    }
	    break;

	case 'F':
	    cf->stable.no_check = 1;
	    break;

	case 'i':
	    cf->stable.ttl_mode = TTL_INDEPENDENT;
	    break;

	case 'n':
	    if(strncmp("unix:", optarg, 5) == 0)
		optarg += 5;
	    if(strlen(optarg) == 0)
		errx(1, "timeout notification socket name too short");
	    cf->timeout_socket = optarg;
	    break;

	case 'P':
	    cf->stable.record_pcap = 1;
	    break;

	case 'a':
	    cf->stable.record_all = 1;
	    break;

	case 'd':
	    cp = strchr(optarg, ':');
	    if (cp != NULL) {
		cf->stable.log_facility = rtpp_log_str2fac(cp + 1);
		if (cf->stable.log_facility == -1)
		    errx(1, "%s: invalid log facility", cp + 1);
		*cp = '\0';
	    }
	    cf->stable.log_level = rtpp_log_str2lvl(optarg);
	    if (cf->stable.log_level == -1)
		errx(1, "%s: invalid log level", optarg);
	    break;

	case '?':
	default:
	    usage();
	}
    if (cf->stable.rdir == NULL && cf->stable.sdir != NULL)
	errx(1, "-S switch requires -r switch");

    if (cf->stable.no_check == 0 && getuid() == 0 && cf->stable.run_uname == NULL) {
	if (cf->stable.umode != 0) {
	    errx(1, "running this program as superuser in a remote control "
	      "mode is strongly not recommended, as it poses serious security "
	      "threat to your system. Use -u option to run as an unprivileged "
	      "user or -F is you want to run as a superuser anyway.");
	} else {
	    warnx("WARNING!!! Running this program as superuser is strongly "
	      "not recommended, as it may pose serious security threat to "
	      "your system. Use -u option to run as an unprivileged user "
	      "or -F to surpress this warning.");
	}
    }

    /* make sure that port_min and port_max are even */
    if ((cf->stable.port_min % 2) != 0)
	cf->stable.port_min++;
    if ((cf->stable.port_max % 2) != 0) {
	cf->stable.port_max--;
    } else {
	/*
	 * If port_max is already even then there is no
	 * "room" for the RTCP port, go back by two ports.
	 */
	cf->stable.port_max -= 2;
    }

    if (!IS_VALID_PORT(cf->stable.port_min))
	errx(1, "invalid value of the port_min argument, "
	  "not in the range 1-65535");
    if (!IS_VALID_PORT(cf->stable.port_max))
	errx(1, "invalid value of the port_max argument, "
	  "not in the range 1-65535");
    if (cf->stable.port_min > cf->stable.port_max)
	errx(1, "port_min should be less than port_max");

    cf->sessinfo.sessions = malloc((sizeof cf->sessinfo.sessions[0]) *
      (((cf->stable.port_max - cf->stable.port_min + 1) * 2) + 1));
    cf->rtp_servers =  malloc((sizeof cf->rtp_servers[0]) *
      (((cf->stable.port_max - cf->stable.port_min + 1) * 2) + 1));
    cf->sessinfo.pfds = malloc((sizeof cf->sessinfo.pfds[0]) *
      (((cf->stable.port_max - cf->stable.port_min + 1) * 2) + 1));

    if (bh[0] == NULL && bh[1] == NULL && bh6[0] == NULL && bh6[1] == NULL) {
	bh[0] = "*";
    }

    for (i = 0; i < 2; i++) {
	if (bh[i] != NULL && *bh[i] == '\0')
	    bh[i] = NULL;
	if (bh6[i] != NULL && *bh6[i] == '\0')
	    bh6[i] = NULL;
    }

    i = ((bh[0] == NULL) ? 0 : 1) + ((bh[1] == NULL) ? 0 : 1) +
      ((bh6[0] == NULL) ? 0 : 1) + ((bh6[1] == NULL) ? 0 : 1);
    if (cf->stable.bmode != 0) {
	if (bh[0] != NULL && bh6[0] != NULL)
	    errx(1, "either IPv4 or IPv6 should be configured for external "
	      "interface in bridging mode, not both");
	if (bh[1] != NULL && bh6[1] != NULL)
	    errx(1, "either IPv4 or IPv6 should be configured for internal "
	      "interface in bridging mode, not both");
	if (i != 2)
	    errx(1, "incomplete configuration of the bridging mode - exactly "
	      "2 listen addresses required, %d provided", i);
    } else if (i != 1) {
	errx(1, "exactly 1 listen addresses required, %d provided", i);
    }

    for (i = 0; i < 2; i++) {
	cf->stable.bindaddr[i] = NULL;
	if (bh[i] != NULL) {
	    cf->stable.bindaddr[i] = host2bindaddr(cf, bh[i], AF_INET, &errmsg);
	    if (cf->stable.bindaddr[i] == NULL)
		errx(1, "host2bindaddr: %s", errmsg);
	    continue;
	}
	if (bh6[i] != NULL) {
	    cf->stable.bindaddr[i] = host2bindaddr(cf, bh6[i], AF_INET6, &errmsg);
	    if (cf->stable.bindaddr[i] == NULL)
		errx(1, "host2bindaddr: %s", errmsg);
	    continue;
	}
    }
    if (cf->stable.bindaddr[0] == NULL) {
	cf->stable.bindaddr[0] = cf->stable.bindaddr[1];
	cf->stable.bindaddr[1] = NULL;
    }
}