} else if (rde_req_list_exists(nbr, &lsa->hdr)) {  free(lsa); imsg_compose(ibuf_ospfe, IMSG_LS_BADREQ, imsg.hdr.peerid, 0, -1, NULL, 0);
rde_dispatch_imsg(int fd, short event, void *bula){	struct imsgbuf		*ibuf = bula;	struct imsg		 imsg;	struct in_addr		 aid;	struct ls_req_hdr	 req_hdr;	struct lsa_hdr		 lsa_hdr, *db_hdr;	struct rde_nbr		 rn, *nbr;	struct lsa		*lsa;	struct area		*area;	struct vertex		*v;	char			*buf;	time_t			 now;	int			 r, n, state, self;	u_int16_t		 l;	switch (event) {	case EV_READ:		if ((n = imsg_read(ibuf)) == -1)			fatal("imsg_read error");		if (n == 0)	/* connection closed */			fatalx("pipe closed");		break;	case EV_WRITE:		if (msgbuf_write(&ibuf->w) == -1)			fatal("msgbuf_write");		imsg_event_add(ibuf);		return;	default:		fatalx("unknown event");	}	now = time(NULL);	for (;;) {		if ((n = imsg_get(ibuf, &imsg)) == -1)			fatal("rde_dispatch_imsg: imsg_read error");		if (n == 0)			break;		switch (imsg.hdr.type) {		case IMSG_NEIGHBOR_UP:			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(rn))				fatalx("invalid size of OE request");			memcpy(&rn, imsg.data, sizeof(rn));			if (rde_nbr_find(imsg.hdr.peerid))				fatalx("rde_dispatch_imsg: "				    "neighbor already exists");			rde_nbr_new(imsg.hdr.peerid, &rn);			break;		case IMSG_NEIGHBOR_DOWN:			rde_nbr_del(rde_nbr_find(imsg.hdr.peerid));			break;		case IMSG_NEIGHBOR_CHANGE:			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(state))				fatalx("invalid size of OE request");			memcpy(&state, imsg.data, sizeof(state));			nbr = rde_nbr_find(imsg.hdr.peerid);			if (nbr == NULL)				fatalx("rde_dispatch_imsg: "				    "neighbor does not exist");			nbr->state = state;			if (nbr->state & NBR_STA_FULL)				rde_req_list_free(nbr);			break;		case IMSG_DB_SNAPSHOT:			nbr = rde_nbr_find(imsg.hdr.peerid);			if (nbr == NULL)				fatalx("rde_dispatch_imsg: "				    "neighbor does not exist");			lsa_snap(nbr->area, imsg.hdr.peerid);			imsg_compose(ibuf_ospfe, IMSG_DB_END, imsg.hdr.peerid,			    0, -1, NULL, 0);			break;		case IMSG_DD:			nbr = rde_nbr_find(imsg.hdr.peerid);			if (nbr == NULL)				fatalx("rde_dispatch_imsg: "				    "neighbor does not exist");			buf = imsg.data;			for (l = imsg.hdr.len - IMSG_HEADER_SIZE;			    l >= sizeof(lsa_hdr); l -= sizeof(lsa_hdr)) {				memcpy(&lsa_hdr, buf, sizeof(lsa_hdr));				buf += sizeof(lsa_hdr);				v = lsa_find(nbr->area, lsa_hdr.type,				    lsa_hdr.ls_id, lsa_hdr.adv_rtr);				if (v == NULL)					db_hdr = NULL;				else					db_hdr = &v->lsa->hdr;				if (lsa_newer(&lsa_hdr, db_hdr) > 0) {					/*					 * only request LSA's that are					 * newer or missing					 */					rde_req_list_add(nbr, &lsa_hdr);					imsg_compose(ibuf_ospfe, IMSG_DD,					    imsg.hdr.peerid, 0, -1,					    &lsa_hdr, sizeof(lsa_hdr));				}			}			if (l != 0)				log_warnx("rde_dispatch_imsg: peerid %lu, "				    "trailing garbage in Database Description "				    "packet", imsg.hdr.peerid);			imsg_compose(ibuf_ospfe, IMSG_DD_END, imsg.hdr.peerid,			    0, -1, NULL, 0);			break;		case IMSG_LS_REQ:			nbr = rde_nbr_find(imsg.hdr.peerid);			if (nbr == NULL)				fatalx("rde_dispatch_imsg: "				    "neighbor does not exist");			buf = imsg.data;			for (l = imsg.hdr.len - IMSG_HEADER_SIZE;			    l >= sizeof(req_hdr); l -= sizeof(req_hdr)) {				memcpy(&req_hdr, buf, sizeof(req_hdr));				buf += sizeof(req_hdr);				if ((v = lsa_find(nbr->area,				    ntohl(req_hdr.type), req_hdr.ls_id,				    req_hdr.adv_rtr)) == NULL) {					imsg_compose(ibuf_ospfe, IMSG_LS_BADREQ,					    imsg.hdr.peerid, 0, -1, NULL, 0);					continue;				}				imsg_compose(ibuf_ospfe, IMSG_LS_UPD,				    imsg.hdr.peerid, 0, -1,				    v->lsa, ntohs(v->lsa->hdr.len));			}			if (l != 0)				log_warnx("rde_dispatch_imsg: peerid %lu, "				    "trailing garbage in LS Request "				    "packet", imsg.hdr.peerid);			break;		case IMSG_LS_UPD:			nbr = rde_nbr_find(imsg.hdr.peerid);			if (nbr == NULL)				fatalx("rde_dispatch_imsg: "				    "neighbor does not exist");			lsa = malloc(imsg.hdr.len - IMSG_HEADER_SIZE);			if (lsa == NULL)				fatal(NULL);			memcpy(lsa, imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);			if (!lsa_check(nbr, lsa,			    imsg.hdr.len - IMSG_HEADER_SIZE)) {				free(lsa);				break;			}			v = lsa_find(nbr->area, lsa->hdr.type, lsa->hdr.ls_id,				    lsa->hdr.adv_rtr);			if (v == NULL)				db_hdr = NULL;			else				db_hdr = &v->lsa->hdr;			if (nbr->self) {				lsa_merge(nbr, lsa, v);				/* lsa_merge frees the right lsa */				break;			}			r = lsa_newer(&lsa->hdr, db_hdr);			if (r > 0) {				/* new LSA newer than DB */				if (v && v->flooded &&				    v->changed + MIN_LS_ARRIVAL >= now) {					free(lsa);					break;				}				if (!(self = lsa_self(nbr, lsa, v)))					lsa_add(nbr, lsa);				rde_req_list_del(nbr, &lsa->hdr);				/* flood and perhaps ack LSA */				imsg_compose(ibuf_ospfe, IMSG_LS_FLOOD,				    imsg.hdr.peerid, 0, -1,				    lsa, ntohs(lsa->hdr.len));				/* reflood self originated LSA */				if (self && v)					imsg_compose(ibuf_ospfe, IMSG_LS_FLOOD,					    v->nbr->peerid, 0, -1,					    v->lsa, ntohs(v->lsa->hdr.len));				/* lsa not added so free it */				if (self)					free(lsa);			} else if (rde_req_list_exists(nbr, &lsa->hdr)) {				/* lsa no longer needed */				free(lsa);				imsg_compose(ibuf_ospfe, IMSG_LS_BADREQ,				    imsg.hdr.peerid, 0, -1, NULL, 0);			} else if (r < 0) {				/* lsa no longer needed */				free(lsa);				/* new LSA older than DB */				if (ntohl(db_hdr->seq_num) == MAX_SEQ_NUM &&				    ntohs(db_hdr->age) == MAX_AGE)					/* seq-num wrap */					break;				if (v->changed + MIN_LS_ARRIVAL >= now)					break;				/* directly send current LSA, no ack */				imsg_compose(ibuf_ospfe, IMSG_LS_UPD,				    imsg.hdr.peerid, 0, -1,				    v->lsa, ntohs(v->lsa->hdr.len));			} else {				/* LSA equal send direct ack */				imsg_compose(ibuf_ospfe, IMSG_LS_ACK,				    imsg.hdr.peerid, 0, -1, &lsa->hdr,				    sizeof(lsa->hdr));				free(lsa);			}			break;		case IMSG_LS_MAXAGE:			nbr = rde_nbr_find(imsg.hdr.peerid);			if (nbr == NULL)				fatalx("rde_dispatch_imsg: "				    "neighbor does not exist");			if (imsg.hdr.len != IMSG_HEADER_SIZE +			    sizeof(struct lsa_hdr))				fatalx("invalid size of OE request");			memcpy(&lsa_hdr, imsg.data, sizeof(lsa_hdr));			aid.s_addr = lsa_hdr.ls_id;			log_debug("rde_dispatch_imsg: IMSG_LS_MAXAGE, "			    "type %d ls_id %s", lsa_hdr.type,			    inet_ntoa(aid));			if (rde_nbr_loading(nbr->area)) {				log_debug("IMSG_LS_MAXAGE still loading");				break;			}			v = lsa_find(nbr->area, lsa_hdr.type, lsa_hdr.ls_id,				    lsa_hdr.adv_rtr);			if (v == NULL)				db_hdr = NULL;			else				db_hdr = &v->lsa->hdr;			/*			 * only delete LSA if the one in the db is not newer			 */			if (lsa_newer(db_hdr, &lsa_hdr) <= 0)				lsa_del(nbr, &lsa_hdr);			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:			if (imsg.hdr.len != IMSG_HEADER_SIZE &&			    imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(aid)) {				log_warnx("rde_dispatch: wrong imsg len");				break;			}			if (imsg.hdr.len == IMSG_HEADER_SIZE) {				LIST_FOREACH(area, &rdeconf->area_list, entry) {					imsg_compose(ibuf_ospfe, IMSG_CTL_AREA,					    0, imsg.hdr.pid, -1, area,					    sizeof(*area));					lsa_dump(&area->lsa_tree, imsg.hdr.type,					    imsg.hdr.pid);				}				lsa_dump(&rdeconf->lsa_tree, imsg.hdr.type,				    imsg.hdr.pid);			} else {				memcpy(&aid, imsg.data, sizeof(aid));				if ((area = area_find(rdeconf, aid)) != NULL) {					imsg_compose(ibuf_ospfe, IMSG_CTL_AREA,					    0, imsg.hdr.pid, -1, area,					    sizeof(*area));					lsa_dump(&area->lsa_tree, imsg.hdr.type,					    imsg.hdr.pid);					if (!area->stub)						lsa_dump(&rdeconf->lsa_tree,						    imsg.hdr.type,						    imsg.hdr.pid);				}			}			imsg_compose(ibuf_ospfe, IMSG_CTL_END, 0, imsg.hdr.pid,			    -1, NULL, 0);			break;		case IMSG_CTL_SHOW_RIB:			LIST_FOREACH(area, &rdeconf->area_list, entry) {				imsg_compose(ibuf_ospfe, IMSG_CTL_AREA,				    0, imsg.hdr.pid, -1, area,				    sizeof(*area));				rt_dump(area->id, imsg.hdr.pid, RIB_RTR);				rt_dump(area->id, imsg.hdr.pid, RIB_NET);			}			aid.s_addr = 0;			rt_dump(aid, imsg.hdr.pid, RIB_EXT);			imsg_compose(ibuf_ospfe, IMSG_CTL_END, 0, imsg.hdr.pid,			    -1, NULL, 0);			break;		case IMSG_CTL_SHOW_SUM:			rde_send_summary(imsg.hdr.pid);			LIST_FOREACH(area, &rdeconf->area_list, entry)				rde_send_summary_area(area, imsg.hdr.pid);			imsg_compose(ibuf_ospfe, IMSG_CTL_END, 0, imsg.hdr.pid,			    -1, NULL, 0);			break;		default:			log_debug("rde_dispatch_msg: unexpected imsg %d",			    imsg.hdr.type);			break;		}		imsg_free(&imsg);	}	imsg_event_add(ibuf);}