case IMSG_CTL_END:
session_dispatch_imsg(struct imsgbuf *ibuf, int idx){	struct imsg		 imsg;	struct mrt_config	 xmrt;	struct mrt_config	*mrt;	struct peer_config	*pconf;	struct peer		*p, *next;	u_char			*data;	enum reconf_action	 reconf;	int			 n;	u_int8_t		 errcode, subcode;	if ((n = imsg_read(ibuf)) == -1)		fatal("session_dispatch_imsg: imsg_read error");	if (n == 0)	/* connection closed */		fatal("session_dispatch_imsg: pipe closed");	for (;;) {		if ((n = imsg_get(ibuf, &imsg)) == -1)			fatal("session_dispatch_imsg: imsg_get error");		if (n == 0)			break;		switch (imsg.hdr.type) {		case IMSG_RECONF_CONF:			if (idx != PFD_PIPE_MAIN)				fatalx("reconf request not from parent");			if ((nconf = malloc(sizeof(struct bgpd_config))) ==			    NULL)				fatal(NULL);			memcpy(nconf, imsg.data, sizeof(struct bgpd_config));			npeers = NULL;			init_conf(nconf);			pending_reconf = 1;			break;		case IMSG_RECONF_PEER:			if (idx != PFD_PIPE_MAIN)				fatalx("reconf request not from parent");			pconf = imsg.data;			p = getpeerbyaddr(&pconf->remote_addr);			if (p == NULL) {				if ((p = calloc(1, sizeof(struct peer))) ==				    NULL)					fatal("new_peer");				p->state = STATE_NONE;				p->next = npeers;				npeers = p;				reconf = RECONF_REINIT;			} else				reconf = RECONF_KEEP;			memcpy(&p->conf, pconf, sizeof(struct peer_config));			p->conf.reconf_action = reconf;			break;		case IMSG_RECONF_DONE:			if (idx != PFD_PIPE_MAIN)				fatalx("reconf request not from parent");			if (nconf == NULL)				fatalx("got IMSG_RECONF_DONE but no config");			conf->as = nconf->as;			conf->holdtime = nconf->holdtime;			conf->bgpid = nconf->bgpid;			conf->min_holdtime = nconf->min_holdtime;			/* add new peers */			for (p = npeers; p != NULL; p = next) {				next = p->next;				p->next = peers;				peers = p;			}			/* find peers to be deleted */			for (p = peers; p != NULL; p = p->next)				if (p->conf.reconf_action == RECONF_NONE)					p->conf.reconf_action = RECONF_DELETE;			free(nconf);			nconf = NULL;			pending_reconf = 0;			log_info("SE reconfigured");			break;		case IMSG_MRT_REQ:			if ((mrt = calloc(1, sizeof(struct mrt_config))) ==			    NULL)				fatal("session_dispatch_imsg");			memcpy(mrt, imsg.data, sizeof(struct mrt_config));			mrt->ibuf = &ibuf_main;			LIST_INSERT_HEAD(&mrt_l, mrt, list);			break;		case IMSG_MRT_END:			memcpy(&xmrt, imsg.data, sizeof(struct mrt_config));			LIST_FOREACH(mrt, &mrt_l, list) {				if (mrt->type != xmrt.type)					continue;				if (mrt->peer_id == xmrt.peer_id &&				    mrt->group_id == xmrt.group_id) {					LIST_REMOVE(mrt, list);					free(mrt);					break;				}			}			break;		case IMSG_CTL_KROUTE:		case IMSG_CTL_KROUTE_ADDR:		case IMSG_CTL_SHOW_NEXTHOP:		case IMSG_CTL_SHOW_INTERFACE:		case IMSG_CTL_END:			if (idx != PFD_PIPE_MAIN)				fatalx("ctl kroute request not from parent");			control_imsg_relay(&imsg);			break;		case IMSG_UPDATE:			if (idx != PFD_PIPE_ROUTE)				fatalx("update request not from RDE");			if (imsg.hdr.len > IMSG_HEADER_SIZE +			    MAX_PKTSIZE - MSGSIZE_HEADER ||			    imsg.hdr.len < IMSG_HEADER_SIZE +			    MSGSIZE_UPDATE_MIN - MSGSIZE_HEADER)				log_warnx("RDE sent invalid update");			else				session_update(imsg.hdr.peerid, imsg.data,				    imsg.hdr.len - IMSG_HEADER_SIZE);			break;		case IMSG_UPDATE_ERR:			if (idx != PFD_PIPE_ROUTE)				fatalx("update request not from RDE");			if (imsg.hdr.len < IMSG_HEADER_SIZE + 2) {				log_warnx("RDE sent invalid notification");				break;			}			if ((p = getpeerbyid(imsg.hdr.peerid)) == NULL) {				log_warnx("no such peer: id=%u",				    imsg.hdr.peerid);				break;			}			data = imsg.data;			errcode = *data++;			subcode = *data++;			if (imsg.hdr.len == IMSG_HEADER_SIZE + 2)				data = NULL;			session_notification(p, errcode, subcode,			    data, imsg.hdr.len - IMSG_HEADER_SIZE - 2);			break;		default:			break;		}		imsg_free(&imsg);	}}