[net.bugs.4bsd] Bug in ip_input.c

rickk@tekchips.UUCP (07/10/84)

This bug can cause havoc with the ip_protox array whose values are used
as an index into the protosw.  Most likely, this doesn't affect anyone but
may well at some later point.  The original code looks one entry to far
in the protosw in ip_init when setting up ip_protox.  Depending on what
data follows the protosw table, one will get an incorrect value in ip_protox.
Since most of the entries (all but 3 or 4), are set to an index for IPPROTO_RAW
and never used, the chances of hitting this bug is rare.

Simple fix (of an oversight):
Change a <= to a <.

ip_input.c
----------
old version
-----------

/*
 * IP initialization: fill in IP protocol switch table.
 * All protocols not implemented in kernel go to raw IP protocol handler.
 */
ip_init()
{
	register struct protosw *pr;
	register int i;

	pr = pffindproto(PF_INET, IPPROTO_RAW);
	if (pr == 0)
		panic("ip_init");
	for (i = 0; i < IPPROTO_MAX; i++)
		ip_protox[i] = pr - inetsw;
	for (pr = inetdomain.dom_protosw;
	    pr <= inetdomain.dom_protoswNPROTOSW; pr++) /*** BUG ***/
		if (pr->pr_family == PF_INET &&
		    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
			ip_protox[pr->pr_protocol] = pr - inetsw;
	ipq.next = ipq.prev = &ipq;
	ip_id = time.tv_sec & 0xffff;
	ipintrq.ifq_maxlen = ipqmaxlen;
	ifinet = if_ifwithaf(AF_INET);
}

new version
___________

/*
 * IP initialization: fill in IP protocol switch table.
 * All protocols not implemented in kernel go to raw IP protocol handler.
 */
ip_init()
{
	register struct protosw *pr;
	register int i;

	pr = pffindproto(PF_INET, IPPROTO_RAW);
	if (pr == 0)
		panic("ip_init");
	for (i = 0; i < IPPROTO_MAX; i++)
		ip_protox[i] = pr - inetsw;
	for (pr = inetdomain.dom_protosw;
	    pr < inetdomain.dom_protoswNPROTOSW; pr++)  /*** FIXED ***/
		if (pr->pr_family == PF_INET &&
		    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
			ip_protox[pr->pr_protocol] = pr - inetsw;
	ipq.next = ipq.prev = &ipq;
	ip_id = time.tv_sec & 0xffff;
	ipintrq.ifq_maxlen = ipqmaxlen;
	ifinet = if_ifwithaf(AF_INET);
}