rem: if (len < sizeof(*rtm) || len != (mtod(m, struct rt_msghdr*))->rtm_msglen) {
add: if (len < (int) sizeof(*rtm) || len != (mtod(m, struct rt_msghdr*))->rtm_msglen) {
context: int route_output(struct mbuf *m, struct socket *so){	struct rt_msghdr *rtm = NULL;	struct rtentry *rt = NULL;	struct rtentry *saved_nrt = NULL;	struct rt_addrinfo info;	int len;	int error = 0;	struct ifnet *ifp = NULL;	struct ifaddr *ifa = NULL;	#define snderr(e) { error = e; goto flush; }	if (m == NULL || ((m->m_len < sizeof(int32)) &&	    ((m = m_pullup(m, sizeof(int32))) == NULL))) {		printf("route_output: ENOBUFS (m_pullup)\n");		if (m)			printf("m = %p, m_len = %ld\n", m, m->m_len);		return ENOBUFS;	}		if ((m->m_flags & M_PKTHDR) == 0) {		printf("route_output: Not packet header\n");		return -1;	}	len = m->m_pkthdr.len;	if (len < sizeof(*rtm) || len != (mtod(m, struct rt_msghdr*))->rtm_msglen) {		info.rti_info[RTAX_DST] = NULL;		printf("route_output: EINVAL\n");		snderr(EINVAL);	}	R_Malloc(rtm, struct rt_msghdr *, len);	if (rtm == NULL) {		info.rti_info[RTAX_DST] = NULL;		printf("route_output: ENOBUFS (rtm == NULL)\n");		snderr(ENOBUFS);	}	m_copydata(m, 0, len, (caddr_t)rtm);	if (rtm->rtm_version != RTM_VERSION) {		info.rti_info[RTAX_DST] = NULL;		printf("route_output: EPROTONOSUPPORT\n");		snderr(EPROTONOSUPPORT);	}		info.rti_addrs = rtm->rtm_addrs;	rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info);		if (info.rti_info[RTAX_DST] == NULL)		snderr(EINVAL);	if (info.rti_info[RTAX_GENMASK]) {		struct radix_node *t;		t = rn_addmask((caddr_t)info.rti_info[RTAX_GENMASK], 1, 2);		if (t && Bcmp(info.rti_info[RTAX_GENMASK], t->rn_key, *(uint8*)info.rti_info[RTAX_GENMASK]) == 0)			info.rti_info[RTAX_GENMASK] = (struct sockaddr *)t->rn_key;		else			snderr(ENOBUFS);	}		switch (rtm->rtm_type) {		case RTM_ADD:			if (info.rti_info[RTAX_GATEWAY] == NULL) {				printf("route_output: EINVAL\n");				snderr(EINVAL);			}			error = rtrequest(RTM_ADD, info.rti_info[RTAX_DST], info.rti_info[RTAX_GATEWAY],			                  info.rti_info[RTAX_NETMASK], rtm->rtm_flags, &saved_nrt);			if (error == 0 && saved_nrt) {				rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, &saved_nrt->rt_rmx);				saved_nrt->rt_refcnt--;				saved_nrt->rt_genmask = info.rti_info[RTAX_GENMASK];			}			break;		case RTM_DELETE:			error = rtrequest(RTM_DELETE, info.rti_info[RTAX_DST], info.rti_info[RTAX_GATEWAY],			                  info.rti_info[RTAX_NETMASK], rtm->rtm_flags, NULL);			break;		case RTM_GET:		case RTM_CHANGE:		case RTM_LOCK:			rt = rtalloc1(info.rti_info[RTAX_DST], 0);			if (rt == NULL) {				printf("route_output: ESRCH\n");				snderr(ESRCH);			}			if (rtm->rtm_type != RTM_GET) {				struct radix_node *rn;				if (Bcmp(info.rti_info[RTAX_DST], rt_key(rt), 				         info.rti_info[RTAX_DST]->sa_len) != 0)					snderr(ESRCH);				if (info.rti_info[RTAX_NETMASK] &&				    (rn = rn_head_search(info.rti_info[RTAX_NETMASK])))					info.rti_info[RTAX_NETMASK] = (struct sockaddr*)rn->rn_key;				for (rn = rt->rt_nodes; rn; rn = rn->rn_dupedkey)					if (info.rti_info[RTAX_NETMASK] == (struct sockaddr*)rn->rn_mask)						break;				if (rn == NULL) {					printf("route_output: ETOOMANYREFS\n");					snderr(EINVAL);//ETOOMANYREFS;				}				rt = (struct rtentry *)rn;			}			switch (rtm->rtm_type) {				case RTM_GET:					info.rti_info[RTAX_DST] = rt_key(rt);					info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;					info.rti_info[RTAX_NETMASK] = rt_mask(rt);					info.rti_info[RTAX_GENMASK] = rt->rt_genmask;					if (rtm->rtm_addrs && (RTA_IFP | RTA_IFA)) {						if ((ifp = rt->rt_ifp)) {							info.rti_info[RTAX_IFA] = ifp->if_addrlist->ifa_addr;							info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;							rtm->rtm_index = ifp->if_index;						} else {							info.rti_info[RTAX_IFA] = NULL;							info.rti_info[RTAX_IFA] = NULL;						}					}					len = rt_msg2(RTM_GET, &info, NULL, NULL);					if (len > rtm->rtm_msglen) {						struct rt_msghdr *new_rtm ;						R_Malloc(new_rtm, struct rt_msghdr *, len);						if (new_rtm == NULL)							snderr(ENOBUFS);						Bcopy(rtm, new_rtm, rtm->rtm_msglen);						Free(rtm);						rtm = new_rtm;					}					(void)rt_msg2(RTM_GET, &info, (caddr_t)rtm, NULL);					rtm->rtm_flags = rt->rt_flags;					rtm->rtm_rmx = rt->rt_rmx;					rtm->rtm_addrs = info.rti_addrs;					break;				case RTM_CHANGE:					if (info.rti_info[RTAX_GATEWAY] && rt_setgate(rt, rt_key(rt), info.rti_info[RTAX_GATEWAY])) {						printf("route_output: EDQUOT\n");						snderr(EINVAL); //EDQUOT ???					}					/* new gateway could require a new ifaddr and ifp, flags might also					 * be different. ifp may be specified by link level sockaddr when					 * protocol address is ambiguous...					 */					if (info.rti_info[RTAX_IFA] && 					    (ifa = ifa_ifwithnet(info.rti_info[RTAX_IFA])) &&					    (ifp = ifa->ifa_ifp))						ifa = ifaof_ifpforaddr(info.rti_info[RTAX_IFA] ?						                        info.rti_info[RTAX_IFA] : 						                        info.rti_info[RTAX_GATEWAY],						                       ifp);					else if ((info.rti_info[RTAX_IFA] && (ifa = ifa_ifwithaddr(info.rti_info[RTAX_IFA]))) ||					         (ifa = ifa_ifwithroute(rt->rt_flags, rt_key(rt), info.rti_info[RTAX_GATEWAY])))						ifp = ifa->ifa_ifp;					if (ifa) {						struct ifaddr *oifa = rt->rt_ifa;						if (oifa != ifa) {							if (oifa && oifa->ifa_rtrequest)								oifa->ifa_rtrequest(RTM_DELETE, rt, info.rti_info[RTAX_GATEWAY]);							IFAFREE(rt->rt_ifa);							rt->rt_ifa = ifa;							ifa->ifa_refcnt++;							rt->rt_ifp = ifp;						}					}					rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, &rt->rt_rmx);					if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)						rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, info.rti_info[RTAX_GATEWAY]);					if (info.rti_info[RTAX_GENMASK])						rt->rt_genmask = info.rti_info[RTAX_GENMASK];					/* fall through... */				case RTM_LOCK:					rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);					rt->rt_rmx.rmx_locks |= (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);					break;			}			break;		default:			printf("route_output: EOPNOTSUPP\n");			snderr(EINVAL); //EOPNOTSUPP;	}	flush:		if (rtm) {		if (error)			rtm->rtm_errno = error;		else			rtm->rtm_flags |= RTF_DONE;	}	if (rt)		rtfree(rt);	{		struct rawcb *rp = NULL;		/* check if it's our own message! */		if ((so->so_options & SO_USELOOPBACK) == 0) {			if (route_cb.any_count <= 1) {				if (rtm)					Free(rtm);				m_freem(m);				return error;			}			rp = sotorawcb(so);		}		if (rtm) {			m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);			Free(rtm);		}		if (rp)			rp->rcb_proto.sp_family = 0;		if (info.rti_info[RTAX_DST])			route_proto.sp_protocol = info.rti_info[RTAX_DST]->sa_family;		raw_input(m, &route_proto, &route_src, &route_dst);		if (rp)			rp->rcb_proto.sp_family = PF_ROUTE;	}	return error;}