Пример #1
0
int
show_nbr_msg(struct imsg *imsg)
{
	struct ctl_nbr	*nbr;
	char		*state;

	switch (imsg->hdr.type) {
	case IMSG_CTL_SHOW_NBR:
		nbr = imsg->data;
		if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state),
		    if_state_name(nbr->iface_state)) == -1)
			err(1, NULL);
		printf("%-15s %-3d %-12s %-10s", inet_ntoa(nbr->id),
		    nbr->priority, state, fmt_timeframe_core(nbr->dead_timer));
		printf("%-11s %s\n", nbr->name,
		    nbr->uptime == 0 ? "-" : fmt_timeframe_core(nbr->uptime));
		free(state);
		break;
	case IMSG_CTL_END:
		printf("\n");
		return (1);
	default:
		break;
	}

	return (0);
}
Пример #2
0
int
show_nbr_msg(struct imsg *imsg)
{
	struct ctl_nbr	*nbr;

	switch (imsg->hdr.type) {
	case IMSG_CTL_SHOW_NBR:
		nbr = imsg->data;
		printf("%-15s %-19s", inet_ntoa(nbr->id),
		    nbr_state_name(nbr->nbr_state));
		printf("%-15s %-15s\n", inet_ntoa(nbr->addr),
		    nbr->uptime == 0 ? "-" : fmt_timeframe_core(nbr->uptime));
		break;
	case IMSG_CTL_END:
		printf("\n");
		return (1);
	default:
		break;
	}

	return (0);
}
Пример #3
0
int
show_nbr_detail_msg(struct imsg *imsg)
{
	struct ctl_nbr	*nbr;

	switch (imsg->hdr.type) {
	case IMSG_CTL_SHOW_NBR:
		nbr = imsg->data;
		printf("\nNeighbor %s, ", inet_ntoa(nbr->id));
		printf("interface address %s\n", log_in6addr(&nbr->addr));
		printf("  Area %s, interface %s\n", inet_ntoa(nbr->area),
		    nbr->name);
		printf("  Neighbor priority is %d, "
		    "State is %s, %d state changes\n",
		    nbr->priority, nbr_state_name(nbr->nbr_state),
		    nbr->state_chng_cnt);
		printf("  DR is %s, ", inet_ntoa(nbr->dr));
		printf("BDR is %s\n", inet_ntoa(nbr->bdr));
		printf("  Options %s\n", print_ospf_options(nbr->options));
		printf("  Dead timer due in %s\n",
		    fmt_timeframe_core(nbr->dead_timer));
		printf("  Uptime %s\n", fmt_timeframe_core(nbr->uptime));
		printf("  Database Summary List %d\n", nbr->db_sum_lst_cnt);
		printf("  Link State Request List %d\n", nbr->ls_req_lst_cnt);
		printf("  Link State Retransmission List %d\n",
		    nbr->ls_retrans_lst_cnt);
		break;
	case IMSG_CTL_END:
		printf("\n");
		return (1);
	default:
		break;
	}

	return (0);
}
Пример #4
0
/* database description packet handling */
int
send_db_description(struct nbr *nbr)
{
	struct in6_addr		 dst;
	struct db_dscrp_hdr	 dd_hdr;
	struct lsa_entry	*le, *nle;
	struct ibuf		*buf;
	int			 ret = 0;
	u_int8_t		 bits = 0;

	if ((buf = ibuf_open(nbr->iface->mtu - sizeof(struct ip))) == NULL)
		fatal("send_db_description");

	/* OSPF header */
	if (gen_ospf_hdr(buf, nbr->iface, PACKET_TYPE_DD))
		goto fail;

	/* reserve space for database description header */
	if (ibuf_reserve(buf, sizeof(dd_hdr)) == NULL)
		goto fail;

	switch (nbr->state) {
	case NBR_STA_DOWN:
	case NBR_STA_ATTEMPT:
	case NBR_STA_INIT:
	case NBR_STA_2_WAY:
	case NBR_STA_SNAP:
		log_debug("send_db_description: cannot send packet in state %s,"
		    " neighbor ID %s", nbr_state_name(nbr->state),
		    inet_ntoa(nbr->id));
		ret = -1;
		goto done;
	case NBR_STA_XSTRT:
		bits |= OSPF_DBD_MS | OSPF_DBD_M | OSPF_DBD_I;
		nbr->dd_more = 1;
		break;
	case NBR_STA_XCHNG:
		if (nbr->dd_master)
			bits |= OSPF_DBD_MS;
		else
			bits &= ~OSPF_DBD_MS;

		if (TAILQ_EMPTY(&nbr->db_sum_list)) {
			bits &= ~OSPF_DBD_M;
			nbr->dd_more = 0;
		} else {
			bits |= OSPF_DBD_M;
			nbr->dd_more = 1;
		}

		bits &= ~OSPF_DBD_I;

		/* build LSA list */
		for (le = TAILQ_FIRST(&nbr->db_sum_list); le != NULL &&
		    buf->wpos + sizeof(struct lsa_hdr) < buf->max; le = nle) {
			nbr->dd_end = nle = TAILQ_NEXT(le, entry);
			if (ibuf_add(buf, le->le_lsa, sizeof(struct lsa_hdr)))
				goto fail;
		}
		break;
	case NBR_STA_LOAD:
	case NBR_STA_FULL:
		if (nbr->dd_master)
			bits |= OSPF_DBD_MS;
		else
			bits &= ~OSPF_DBD_MS;
		bits &= ~OSPF_DBD_M;
		bits &= ~OSPF_DBD_I;

		nbr->dd_more = 0;
		break;
	default:
		fatalx("send_db_description: unknown neighbor state");
	}

	bzero(&dd_hdr, sizeof(dd_hdr));

	switch (nbr->iface->type) {
	case IF_TYPE_POINTOPOINT:
		inet_pton(AF_INET6, AllSPFRouters, &dst);
		dd_hdr.iface_mtu = htons(nbr->iface->mtu);
		break;
	case IF_TYPE_BROADCAST:
		dst = nbr->addr;
		dd_hdr.iface_mtu = htons(nbr->iface->mtu);
		break;
	case IF_TYPE_NBMA:
	case IF_TYPE_POINTOMULTIPOINT:
		/* XXX not supported */
		break;
	case IF_TYPE_VIRTUALLINK:
		dst = nbr->iface->dst;
		dd_hdr.iface_mtu = 0;
		break;
	default:
		fatalx("send_db_description: unknown interface type");
	}

	dd_hdr.opts = htonl(area_ospf_options(area_find(oeconf,
	    nbr->iface->area_id)));
	dd_hdr.bits = bits;
	dd_hdr.dd_seq_num = htonl(nbr->dd_seq_num);

	memcpy(ibuf_seek(buf, sizeof(struct ospf_hdr), sizeof(dd_hdr)),
	    &dd_hdr, sizeof(dd_hdr));

	/* calculate checksum */
	if (upd_ospf_hdr(buf, nbr->iface))
		goto fail;

	/* transmit packet */
	ret = send_packet(nbr->iface, buf->buf, buf->wpos, &dst);
done:
	ibuf_free(buf);
	return (ret);
fail:
	log_warn("send_db_description");
	ibuf_free(buf);
	return (-1);
}
Пример #5
0
void
recv_db_description(struct nbr *nbr, char *buf, u_int16_t len)
{
	struct db_dscrp_hdr	 dd_hdr;
	int			 dupe = 0;

	if (len < sizeof(dd_hdr)) {
		log_warnx("recv_db_description: "
		    "bad packet size, neighbor ID %s", inet_ntoa(nbr->id));
		return;
	}
	memcpy(&dd_hdr, buf, sizeof(dd_hdr));
	buf += sizeof(dd_hdr);
	len -= sizeof(dd_hdr);

	/* db description packet sanity checks */
	if (ntohs(dd_hdr.iface_mtu) > nbr->iface->mtu) {
		log_warnx("recv_db_description: invalid MTU %d sent by "
		    "neighbor ID %s, expected %d", ntohs(dd_hdr.iface_mtu),
		    inet_ntoa(nbr->id), nbr->iface->mtu);
		return;
	}

	if (nbr->last_rx_options == dd_hdr.opts &&
	    nbr->last_rx_bits == dd_hdr.bits &&
	    ntohl(dd_hdr.dd_seq_num) == nbr->dd_seq_num - nbr->dd_master ?
	    1 : 0) {
		log_debug("recv_db_description: dupe from ID %s",
		    inet_ntoa(nbr->id));
		dupe = 1;
	}

	switch (nbr->state) {
	case NBR_STA_DOWN:
	case NBR_STA_ATTEMPT:
	case NBR_STA_2_WAY:
	case NBR_STA_SNAP:
		log_debug("recv_db_description: packet ignored in state %s, "
		    "neighbor ID %s", nbr_state_name(nbr->state),
		    inet_ntoa(nbr->id));
		return;
	case NBR_STA_INIT:
		/* evaluate dr and bdr after issuing a 2-Way event */
		nbr_fsm(nbr, NBR_EVT_2_WAY_RCVD);
		if_fsm(nbr->iface, IF_EVT_NBR_CHNG);
		if (nbr->state != NBR_STA_XSTRT)
			return;
		/* FALLTHROUGH */
	case NBR_STA_XSTRT:
		if (dupe)
			return;
		/*
		 * check bits: either I,M,MS or only M
		 */
		if (dd_hdr.bits == (OSPF_DBD_I | OSPF_DBD_M | OSPF_DBD_MS)) {
			/* if nbr Router ID is larger than own -> slave */
			if ((ntohl(nbr->id.s_addr)) >
			    ntohl(ospfe_router_id())) {
				/* slave */
				nbr->dd_master = 0;
				nbr->dd_seq_num = ntohl(dd_hdr.dd_seq_num);

				/* event negotiation done */
				nbr_fsm(nbr, NBR_EVT_NEG_DONE);
			}
		} else if (!(dd_hdr.bits & (OSPF_DBD_I | OSPF_DBD_MS))) {
			/* M only case: we are master */
			if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num) {
				log_warnx("recv_db_description: invalid "
				    "seq num, mine %x his %x",
				    nbr->dd_seq_num, ntohl(dd_hdr.dd_seq_num));
				return;
			}
			nbr->dd_seq_num++;

			/* event negotiation done */
			nbr_fsm(nbr, NBR_EVT_NEG_DONE);

			/* this packet may already have data so pass it on */
			if (len > 0) {
				nbr->dd_pending++;
				ospfe_imsg_compose_rde(IMSG_DD, nbr->peerid,
				    0, buf, len);
			}
		} else {
			/* ignore packet */
			log_debug("recv_db_description: packet ignored in "
			    "state %s (bad flags), neighbor ID %s",
			    nbr_state_name(nbr->state), inet_ntoa(nbr->id));
		}
		break;
	case NBR_STA_XCHNG:
	case NBR_STA_LOAD:
	case NBR_STA_FULL:
		if (dd_hdr.bits & OSPF_DBD_I ||
		    !(dd_hdr.bits & OSPF_DBD_MS) == !nbr->dd_master) {
			log_warnx("recv_db_description: seq num mismatch, "
			    "bad flags");
			nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS);
			return;
		}

		if (nbr->last_rx_options != dd_hdr.opts) {
			log_warnx("recv_db_description: seq num mismatch, "
			    "bad options");
			nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS);
			return;
		}

		if (dupe) {
			if (!nbr->dd_master)
				/* retransmit */
				start_db_tx_timer(nbr);
			return;
		}

		if (nbr->state != NBR_STA_XCHNG) {
			log_warnx("recv_db_description: invalid "
			    "seq num, mine %x his %x",
			    nbr->dd_seq_num, ntohl(dd_hdr.dd_seq_num));
			nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS);
			return;
		}

		/* sanity check dd seq number */
		if (nbr->dd_master) {
			/* master */
			if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num) {
				log_warnx("recv_db_description: invalid "
				    "seq num, mine %x his %x",
				    nbr->dd_seq_num, ntohl(dd_hdr.dd_seq_num));
				nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS);
				return;
			}
			nbr->dd_seq_num++;
		} else {
			/* slave */
			if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num + 1) {
				log_warnx("recv_db_description: invalid "
				    "seq num, mine %x his %x",
				    nbr->dd_seq_num, ntohl(dd_hdr.dd_seq_num));
				nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS);
				return;
			}
			nbr->dd_seq_num = ntohl(dd_hdr.dd_seq_num);
		}

		/* forward to RDE and let it decide which LSAs to request */
		if (len > 0) {
			nbr->dd_pending++;
			ospfe_imsg_compose_rde(IMSG_DD, nbr->peerid, 0,
			    buf, len);
		}

		/* next packet */
		db_sum_list_next(nbr);
		start_db_tx_timer(nbr);

		if (!(dd_hdr.bits & OSPF_DBD_M) &&
		    TAILQ_EMPTY(&nbr->db_sum_list))
			if (!nbr->dd_master || !nbr->dd_more)
				nbr_fsm(nbr, NBR_EVT_XCHNG_DONE);
		break;
	default:
		fatalx("recv_db_description: unknown neighbor state");
	}

	nbr->last_rx_options = dd_hdr.opts;
	nbr->last_rx_bits = dd_hdr.bits;
}