Example #1
0
/* ARGSUSED */
void
control_dispatch_imsg(int fd, short event, void *bula)
{
	struct ctl_conn	*c;
	struct imsg	 imsg;
	ssize_t		 n;
	unsigned int	 ifidx;
	int		 verbose;

	if ((c = control_connbyfd(fd)) == NULL) {
		log_warn("control_dispatch_imsg: fd %d: not found", fd);
		return;
	}

	if (event & EV_READ) {
		if ((n = imsg_read(&c->iev.ibuf)) == -1 || n == 0) {
			control_close(fd);
			return;
		}
	}
	if (event & EV_WRITE) {
		if (msgbuf_write(&c->iev.ibuf.w) == -1) {
			control_close(fd);
			return;
		}
	}

	for (;;) {
		if ((n = imsg_get(&c->iev.ibuf, &imsg)) == -1) {
			control_close(fd);
			return;
		}

		if (n == 0)
			break;

		switch (imsg.hdr.type) {
		case IMSG_CTL_FIB_COUPLE:
		case IMSG_CTL_FIB_DECOUPLE:
			ospfe_fib_update(imsg.hdr.type);
			/* FALLTHROUGH */
		case IMSG_CTL_FIB_RELOAD:
		case IMSG_CTL_RELOAD:
			c->iev.ibuf.pid = imsg.hdr.pid;
			ospfe_imsg_compose_parent(imsg.hdr.type, 0, NULL, 0);
			break;
		case IMSG_CTL_KROUTE:
		case IMSG_CTL_KROUTE_ADDR:
		case IMSG_CTL_IFINFO:
			c->iev.ibuf.pid = imsg.hdr.pid;
			ospfe_imsg_compose_parent(imsg.hdr.type, imsg.hdr.pid,
			    imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
			break;
		case IMSG_CTL_SHOW_INTERFACE:
			if (imsg.hdr.len == IMSG_HEADER_SIZE +
			    sizeof(ifidx)) {
				memcpy(&ifidx, imsg.data, sizeof(ifidx));
				ospfe_iface_ctl(c, ifidx);
				imsg_compose_event(&c->iev, IMSG_CTL_END, 0,
				    0, -1, NULL, 0);
			}
			break;
		case IMSG_CTL_SHOW_DATABASE:
		case IMSG_CTL_SHOW_DB_EXT:
		case IMSG_CTL_SHOW_DB_NET:
		case IMSG_CTL_SHOW_DB_RTR:
		case IMSG_CTL_SHOW_DB_SELF:
		case IMSG_CTL_SHOW_DB_SUM:
		case IMSG_CTL_SHOW_DB_ASBR:
		case IMSG_CTL_SHOW_DB_OPAQ:
		case IMSG_CTL_SHOW_RIB:
		case IMSG_CTL_SHOW_SUM:
			c->iev.ibuf.pid = imsg.hdr.pid;
			ospfe_imsg_compose_rde(imsg.hdr.type, 0, imsg.hdr.pid,
			    imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
			break;
		case IMSG_CTL_SHOW_NBR:
			ospfe_nbr_ctl(c);
			break;
		case IMSG_CTL_LOG_VERBOSE:
			if (imsg.hdr.len != IMSG_HEADER_SIZE +
			    sizeof(verbose))
				break;

			/* forward to other processes */
			ospfe_imsg_compose_parent(imsg.hdr.type, imsg.hdr.pid,
			    imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
			ospfe_imsg_compose_rde(imsg.hdr.type, 0, imsg.hdr.pid,
			    imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);

			memcpy(&verbose, imsg.data, sizeof(verbose));
			log_verbose(verbose);
			break;
		default:
			log_debug("control_dispatch_imsg: "
			    "error handling imsg %d", imsg.hdr.type);
			break;
		}
		imsg_free(&imsg);
	}

	imsg_event_add(&c->iev);
}
Example #2
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;
}