xref: /illumos-gate/usr/src/stand/lib/inet/ipv4.c (revision b531f6d1)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  *
25  * ipv4.c, Code implementing the IPv4 internet protocol.
26  */
27 
28 #include <sys/types.h>
29 #include <socket_impl.h>
30 #include <socket_inet.h>
31 #include <sys/sysmacros.h>
32 #include <sys/socket.h>
33 #include <netinet/in_systm.h>
34 #include <netinet/in.h>
35 #include <netinet/ip.h>
36 #include <netinet/udp.h>
37 #include <net/if_arp.h>
38 #include <sys/promif.h>
39 #include <sys/bootconf.h>
40 #include <sys/fcntl.h>
41 #include <sys/salib.h>
42 
43 #include "icmp4.h"
44 #include "ipv4.h"
45 #include "ipv4_impl.h"
46 #include "mac.h"
47 #include "mac_impl.h"
48 #include "v4_sum_impl.h"
49 #include <sys/bootdebug.h>
50 
51 static struct ip_frag	fragment[FRAG_MAX];	/* ip fragment buffers */
52 static int		fragments;		/* Number of fragments */
53 static uint8_t		ttl = MAXTTL;		/* IP ttl */
54 static struct in_addr	myip;			/* our network-order IP addr */
55 static struct in_addr	mynet;			/* net-order netaddr */
56 static struct in_addr	netmask =
57 	{ 0xff, 0xff, 0xff, 0xff };		/* our network-order netmask */
58 static boolean_t	netmask_set = B_FALSE;	/* has anyone set netmask? */
59 static struct in_addr	defaultrouter;		/* net-order defaultrouter */
60 static int		promiscuous;		/* promiscuous mode */
61 static struct routing table[IPV4_ROUTE_TABLE_SIZE];
62 
63 static uint16_t	g_ip_id;
64 
65 #ifdef	DEBUG
66 #define	FRAG_DEBUG
67 #endif	/* DEBUG */
68 
69 #ifdef FRAG_DEBUG
70 /*
71  * display the fragment list. For debugging purposes.
72  */
73 static void
74 frag_disp(uint16_t size)
75 {
76 	int	i;
77 	uint_t	total = 0;
78 
79 	printf("Dumping fragment info: (%d)\n\n", fragments);
80 	printf("More:\tOffset:\tDatap:\t\tIPid:\t\tIPlen:\tIPhlen:\n");
81 	for (i = 0; i < FRAG_MAX; i++) {
82 		if (fragment[i].mp == NULL)
83 			continue;
84 		printf("%d\t%d\t0x%x\t%d\t\t%d\t%d\n", fragment[i].more,
85 		    fragment[i].offset, fragment[i].mp->b_rptr,
86 		    fragment[i].ipid, fragment[i].iplen, fragment[i].iphlen);
87 		total += (fragment[i].iplen - fragment[i].iphlen);
88 	}
89 	printf("Total length is: %d. It should be: %d\n\n", total, size);
90 }
91 #endif /* FRAG_DEBUG */
92 
93 /*
94  * This function returns index of fragment 0 of the current fragmented DGRAM
95  * (which would contain the transport header). Return the fragment number
96  * for success, -1 if we don't yet have the first fragment.
97  */
98 static int
99 frag_first(void)
100 {
101 	int		i;
102 
103 	if (fragments == 0)
104 		return (-1);
105 
106 	for (i = 0; i < FRAG_MAX; i++) {
107 		if (fragment[i].mp != NULL && fragment[i].offset == 0)
108 			return (i);
109 	}
110 	return (-1);
111 }
112 
113 /*
114  * This function returns index of the last fragment of the current DGRAM.
115  * Returns the fragment number for success, -1 if we don't yet have the
116  * last fragment.
117  */
118 static int
119 frag_last(void)
120 {
121 	int		i;
122 
123 	if (fragments == 0)
124 		return (-1);
125 
126 	for (i = 0; i < FRAG_MAX; i++) {
127 		if (fragment[i].mp != NULL && !fragment[i].more)
128 			return (i);
129 	}
130 	return (-1);
131 }
132 
133 /*
134  * This function adds a fragment to the current pkt fragment list. Returns
135  * FRAG_NOSLOTS if there are no more slots, FRAG_DUP if the fragment is
136  * a duplicate, or FRAG_SUCCESS if it is successful.
137  */
138 static int
139 frag_add(int16_t offset, mblk_t *mp, uint16_t ipid,
140     int16_t iplen, int16_t iphlen, uint8_t ipp)
141 {
142 	int	i;
143 	int16_t	true_offset = IPV4_OFFSET(offset);
144 
145 	/* first pass - look for duplicates */
146 	for (i = 0; i < FRAG_MAX; i++) {
147 		if (fragment[i].mp != NULL &&
148 		    fragment[i].offset == true_offset)
149 			return (FRAG_DUP);
150 	}
151 
152 	/* second pass - fill in empty slot */
153 	for (i = 0; i < FRAG_MAX; i++) {
154 		if (fragment[i].mp == NULL) {
155 			fragment[i].more = (offset & IP_MF);
156 			fragment[i].offset = true_offset;
157 			fragment[i].mp = mp;
158 			fragment[i].ipid = ipid;
159 			fragment[i].iplen = iplen;
160 			fragment[i].iphlen = iphlen;
161 			fragment[i].ipp = ipp;
162 			fragments++;
163 			return (FRAG_SUCCESS);
164 		}
165 	}
166 	return (FRAG_NOSLOTS);
167 }
168 
169 /*
170  * Nuke a fragment.
171  */
172 static void
173 frag_free(int index)
174 {
175 	if (fragment[index].mp != NULL) {
176 		freeb(fragment[index].mp);
177 		fragments--;
178 	}
179 	bzero((caddr_t)&fragment[index], sizeof (struct ip_frag));
180 }
181 
182 /*
183  * zero the frag list.
184  */
185 static void
186 frag_flush(void)
187 {
188 	int i;
189 
190 	for (i = 0; i < FRAG_MAX; i++)
191 		frag_free(i);
192 
193 	fragments = 0;
194 }
195 
196 /*
197  * Analyze the fragment list - see if we captured all our fragments.
198  *
199  * Returns TRUE if we've got all the fragments, and FALSE if we don't.
200  */
201 static int
202 frag_chk(void)
203 {
204 	int		i, first_frag, last_frag;
205 	int16_t		actual, total;
206 	uint16_t	ip_id;
207 	uint8_t		ipp;
208 
209 	if (fragments == 0 || (first_frag = frag_first()) < 0 ||
210 	    (last_frag = frag_last()) < 0)
211 		return (FALSE);
212 
213 	/*
214 	 * Validate the ipid's of our fragments - nuke those that don't
215 	 * match the id of the first fragment or don't match the IP
216 	 * protocol of the first fragment.
217 	 */
218 	ip_id = fragment[first_frag].ipid;
219 	ipp = fragment[first_frag].ipp;
220 	for (i = 0; i < FRAG_MAX; i++) {
221 		if (fragment[i].mp != NULL && ip_id != fragment[i].ipid &&
222 			fragment[i].ipp != ipp) {
223 #ifdef FRAG_DEBUG
224 			printf("ipv4: Frag id mismatch: %x != %x\n",
225 			    fragment[i].ipid, ip_id);
226 #endif /* FRAG_DEBUG */
227 			frag_free(i);
228 		}
229 	}
230 
231 	if (frag_last() < 0)
232 		return (FALSE);
233 
234 	total = fragment[last_frag].offset + fragment[last_frag].iplen -
235 	    fragment[last_frag].iphlen;
236 
237 	for (i = 0, actual = 0; i < FRAG_MAX; i++)
238 		actual += (fragment[i].iplen - fragment[i].iphlen);
239 
240 #ifdef FRAG_DEBUG
241 	frag_disp(total);
242 #endif /* FRAG_DEBUG */
243 
244 	return (total == actual);
245 }
246 
247 /*
248  * Load the assembled fragments into igp. Returns 0 for success, nonzero
249  * otherwise.
250  */
251 static int
252 frag_load(struct inetgram *igp)
253 {
254 	int	i;
255 	int16_t	len;
256 	uint_t	total_len;
257 	boolean_t first_frag = B_FALSE;
258 	mblk_t *mp;
259 	struct ip *iph;
260 	int first_iph_len;
261 
262 	if (fragments == 0)
263 		return (ENOENT);
264 
265 	mp = igp->igm_mp;
266 	/* Get the IP header length of the first fragment. */
267 	i = frag_first();
268 	assert(i >= 0);
269 	first_iph_len = fragment[i].iphlen;
270 	for (i = 0, len = 0, total_len = 0; i < FRAG_MAX; i++) {
271 		if (fragment[i].mp != NULL) {
272 			/*
273 			 * Copy just the data (omit the ip header of all
274 			 * fragments except the first one which contains
275 			 * all the info...)
276 			 */
277 			if (fragment[i].offset == 0) {
278 				len = fragment[i].iplen;
279 				first_frag = B_TRUE;
280 			} else {
281 				len = fragment[i].iplen - fragment[i].iphlen;
282 			}
283 			total_len += len;
284 			if (total_len > mp->b_size)
285 				return (E2BIG);
286 			if (first_frag) {
287 				bcopy((caddr_t)(fragment[i].mp->b_rptr),
288 				    (caddr_t)mp->b_rptr, len);
289 				first_frag = B_FALSE;
290 			} else {
291 				bcopy((caddr_t)(fragment[i].mp->b_rptr +
292 				    fragment[i].iphlen),
293 				    (caddr_t)(mp->b_rptr + first_iph_len +
294 				    fragment[i].offset), len);
295 			}
296 			mp->b_wptr += len;
297 		}
298 	}
299 	/* Fix the total length in the IP header. */
300 	iph = (struct ip *)mp->b_rptr;
301 	iph->ip_len = htons(total_len);
302 	return (0);
303 }
304 
305 /*
306  * Locate a routing table entry based upon arguments. IP addresses expected
307  * in network order. Returns index for success, -1 if entry not found.
308  */
309 static int
310 find_route(uint8_t *flagp, struct in_addr *destp, struct in_addr *gatewayp)
311 {
312 	int i, table_entry = -1;
313 
314 	for (i = 0; table_entry == -1 && i < IPV4_ROUTE_TABLE_SIZE; i++) {
315 		if (flagp != NULL) {
316 			if (*flagp & table[i].flag)
317 				table_entry = i;
318 		}
319 		if (destp != NULL) {
320 			if (destp->s_addr == table[i].dest.s_addr)
321 				table_entry = i;
322 			else
323 				table_entry = -1;
324 		}
325 		if (gatewayp != NULL) {
326 			if (gatewayp->s_addr == table[i].gateway.s_addr)
327 				table_entry = i;
328 			else
329 				table_entry = -1;
330 		}
331 	}
332 	return (table_entry);
333 }
334 
335 /*
336  * ADD or DEL a routing table entry. Returns 0 for success, -1 and errno
337  * otherwise. IP addresses are expected in network order.
338  */
339 int
340 ipv4_route(int cmd, uint8_t flag, struct in_addr *destp,
341     struct in_addr *gatewayp)
342 {
343 	static	int	routing_table_initialized;
344 	int		index;
345 	uint8_t 	tmp_flag;
346 
347 	if (gatewayp == NULL) {
348 		errno = EINVAL;
349 		return (-1);
350 	}
351 
352 	/* initialize routing table */
353 	if (routing_table_initialized == 0) {
354 		for (index = 0; index < IPV4_ROUTE_TABLE_SIZE; index++)
355 			table[index].flag = RT_UNUSED;
356 		routing_table_initialized = 1;
357 	}
358 
359 	switch (cmd) {
360 	case IPV4_ADD_ROUTE:
361 		tmp_flag = (uint8_t)RT_UNUSED;
362 		if ((index = find_route(&tmp_flag, NULL, NULL)) == -1) {
363 			dprintf("ipv4_route: routing table full.\n");
364 			errno = ENOSPC;
365 			return (-1);
366 		}
367 		table[index].flag = flag;
368 		if (destp != NULL)
369 			table[index].dest.s_addr = destp->s_addr;
370 		else
371 			table[index].dest.s_addr = htonl(INADDR_ANY);
372 		table[index].gateway.s_addr = gatewayp->s_addr;
373 		break;
374 	case IPV4_BAD_ROUTE:
375 		/* FALLTHRU */
376 	case IPV4_DEL_ROUTE:
377 		if ((index = find_route(&flag, destp, gatewayp)) == -1) {
378 			dprintf("ipv4_route: No such routing entry.\n");
379 			errno = ENOENT;
380 			return (-1);
381 		}
382 		if (cmd == IPV4_DEL_ROUTE) {
383 			table[index].flag = RT_UNUSED;
384 			table[index].dest.s_addr = htonl(INADDR_ANY);
385 			table[index].gateway.s_addr = htonl(INADDR_ANY);
386 		} else
387 			table[index].flag = RT_NG;
388 	default:
389 		errno = EINVAL;
390 		return (-1);
391 	}
392 	return (0);
393 }
394 
395 /*
396  * Return gateway to destination. Returns gateway IP address in network order
397  * for success, NULL if no route to destination exists.
398  */
399 struct in_addr *
400 ipv4_get_route(uint8_t flag, struct in_addr *destp, struct in_addr *gatewayp)
401 {
402 	int index;
403 	if ((index = find_route(&flag, destp, gatewayp)) == -1)
404 		return (NULL);
405 	return (&table[index].gateway);
406 }
407 
408 /*
409  * Initialize the IPv4 generic parts of the socket, as well as the routing
410  * table.
411  */
412 void
413 ipv4_socket_init(struct inetboot_socket *isp)
414 {
415 	isp->input[NETWORK_LVL] = ipv4_input;
416 	isp->output[NETWORK_LVL] = ipv4_output;
417 	isp->close[NETWORK_LVL] = NULL;
418 	isp->headerlen[NETWORK_LVL] = ipv4_header_len;
419 }
420 
421 /*
422  * Initialize a raw ipv4 socket.
423  */
424 void
425 ipv4_raw_socket(struct inetboot_socket *isp, uint8_t proto)
426 {
427 	isp->type = INETBOOT_RAW;
428 	if (proto == 0)
429 		isp->proto = IPPROTO_IP;
430 	else
431 		isp->proto = proto;
432 	isp->input[TRANSPORT_LVL] = NULL;
433 	isp->output[TRANSPORT_LVL] = NULL;
434 	isp->headerlen[TRANSPORT_LVL] = NULL;
435 	isp->ports = NULL;
436 }
437 
438 /*
439  * Return the size of an IPv4 header (no options)
440  */
441 /* ARGSUSED */
442 int
443 ipv4_header_len(struct inetgram *igm)
444 {
445 	return (sizeof (struct ip));
446 }
447 
448 /*
449  * Set our source address.
450  * Argument is assumed to be host order.
451  */
452 void
453 ipv4_setipaddr(struct in_addr *ip)
454 {
455 	myip.s_addr = htonl(ip->s_addr);
456 }
457 
458 /*
459  * Returns our current source address in host order.
460  */
461 void
462 ipv4_getipaddr(struct in_addr *ip)
463 {
464 	ip->s_addr = ntohl(myip.s_addr);
465 }
466 
467 /*
468  * Set our netmask.
469  * Argument is assumed to be host order.
470  */
471 void
472 ipv4_setnetmask(struct in_addr *ip)
473 {
474 	netmask_set = B_TRUE;
475 	netmask.s_addr = htonl(ip->s_addr);
476 	mynet.s_addr = netmask.s_addr & myip.s_addr; /* implicit */
477 }
478 
479 void
480 ipv4_getnetid(struct in_addr *my_netid)
481 {
482 	struct in_addr my_netmask;
483 	if (mynet.s_addr != 0)
484 		my_netid->s_addr = ntohl(mynet.s_addr);
485 	else {
486 		ipv4_getnetmask(&my_netmask);
487 		my_netid->s_addr = my_netmask.s_addr & ntohl(myip.s_addr);
488 	}
489 }
490 
491 /*
492  * Returns our current netmask in host order.
493  * Neither OBP nor the standalone DHCP client mandate
494  * that the netmask be specified, so in the absence of
495  * a netmask, we attempt to derive it using class-based
496  * heuristics.
497  */
498 void
499 ipv4_getnetmask(struct in_addr *ip)
500 {
501 	if (netmask_set || (myip.s_addr == 0))
502 		ip->s_addr = ntohl(netmask.s_addr);
503 	else {
504 		/* base the netmask on our IP address */
505 		if (IN_CLASSA(ntohl(myip.s_addr)))
506 			ip->s_addr = ntohl(IN_CLASSA_NET);
507 		else if (IN_CLASSB(ntohl(myip.s_addr)))
508 			ip->s_addr = ntohl(IN_CLASSB_NET);
509 		else if (IN_CLASSC(ntohl(myip.s_addr)))
510 			ip->s_addr = ntohl(IN_CLASSC_NET);
511 		else
512 			ip->s_addr = ntohl(IN_CLASSE_NET);
513 	}
514 }
515 
516 /*
517  * Set our default router.
518  * Argument is assumed to be host order, and *MUST* be on the same network
519  * as our source IP address.
520  */
521 void
522 ipv4_setdefaultrouter(struct in_addr *ip)
523 {
524 	defaultrouter.s_addr = htonl(ip->s_addr);
525 }
526 
527 /*
528  * Returns our current default router in host order.
529  */
530 void
531 ipv4_getdefaultrouter(struct in_addr *ip)
532 {
533 	ip->s_addr = ntohl(defaultrouter.s_addr);
534 }
535 
536 /*
537  * Toggle promiscuous flag. If set, client disregards destination IP
538  * address. Otherwise, only limited broadcast, network broadcast, and
539  * unicast traffic get through. Returns previous setting.
540  */
541 int
542 ipv4_setpromiscuous(int toggle)
543 {
544 	int old = promiscuous;
545 
546 	promiscuous = toggle;
547 
548 	return (old);
549 }
550 
551 /*
552  * Set IP TTL.
553  */
554 void
555 ipv4_setmaxttl(uint8_t cttl)
556 {
557 	ttl = cttl;
558 }
559 
560 /*
561  * Convert an ipv4 address to dotted notation.
562  * Returns ptr to statically allocated buffer containing dotted string.
563  */
564 char *
565 inet_ntoa(struct in_addr ip)
566 {
567 	uint8_t *p;
568 	static char ipaddr[16];
569 
570 	p = (uint8_t *)&ip.s_addr;
571 	(void) sprintf(ipaddr, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
572 	return (ipaddr);
573 }
574 
575 /*
576  * Construct a transport datagram from a series of IP fragments (igp == NULL)
577  * or from a single IP datagram (igp != NULL). Return the address of the
578  * contructed transport datagram.
579  */
580 struct inetgram *
581 make_trans_datagram(int index, struct inetgram *igp, struct in_addr ipsrc,
582     struct in_addr ipdst, uint16_t iphlen)
583 {
584 	uint16_t	trans_len, *transp, new_len;
585 	int		first_frag, last_frag;
586 	boolean_t	fragmented;
587 	struct inetgram	*ngp;
588 	struct ip	*iph;
589 
590 	fragmented = (igp == NULL);
591 
592 	ngp = (struct inetgram *)bkmem_zalloc(sizeof (struct inetgram));
593 	if (ngp == NULL) {
594 		errno = ENOMEM;
595 		if (fragmented)
596 			frag_flush();
597 		return (NULL);
598 	}
599 
600 	if (fragmented) {
601 		last_frag = frag_last();
602 		trans_len = fragment[last_frag].offset +
603 		    fragment[last_frag].iplen - fragment[last_frag].iphlen;
604 		first_frag = frag_first();
605 		/*
606 		 * The returned buffer contains the IP header of the
607 		 * first fragment.
608 		 */
609 		trans_len += fragment[first_frag].iphlen;
610 		transp = (uint16_t *)(fragment[first_frag].mp->b_rptr +
611 		    fragment[first_frag].iphlen);
612 	} else {
613 		/*
614 		 * Note that igm_len may not be the real length of an
615 		 * IP packet because some network interface, such as
616 		 * Ethernet, as a minimum frame size.  So we should not
617 		 * use the interface frame size to determine the
618 		 * length of an IP packet.  We should use the IP
619 		 * length field in the IP header.
620 		 */
621 		iph = (struct ip *)igp->igm_mp->b_rptr;
622 		trans_len = ntohs(iph->ip_len);
623 		transp = (uint16_t *)(igp->igm_mp->b_rptr + iphlen);
624 	}
625 
626 	ngp->igm_saddr.sin_addr.s_addr = ipsrc.s_addr;
627 	ngp->igm_saddr.sin_port = sockets[index].ports(transp, SOURCE);
628 	ngp->igm_target.s_addr = ipdst.s_addr;
629 	ngp->igm_level = TRANSPORT_LVL;
630 
631 	/*
632 	 * Align to 16bit value.  Checksum code may require an extra byte
633 	 * for padding.
634 	 */
635 	new_len = ((trans_len + sizeof (int16_t) - 1) &
636 	    ~(sizeof (int16_t) - 1));
637 	if ((ngp->igm_mp = allocb(new_len, 0)) == NULL) {
638 		errno = ENOMEM;
639 		bkmem_free((caddr_t)ngp, sizeof (struct inetgram));
640 		if (fragmented)
641 			frag_flush();
642 		return (NULL);
643 	}
644 
645 	if (fragmented) {
646 		if (frag_load(ngp) != 0) {
647 			freeb(ngp->igm_mp);
648 			bkmem_free((caddr_t)ngp, sizeof (struct inetgram));
649 			frag_flush();
650 			return (NULL);
651 		}
652 		frag_flush();
653 	} else {
654 		bcopy((caddr_t)(igp->igm_mp->b_rptr),
655 		    (caddr_t)ngp->igm_mp->b_rptr, trans_len);
656 		ngp->igm_mp->b_wptr += trans_len;
657 	}
658 	return (ngp);
659 }
660 
661 /*
662  * ipv4_input: Pull in IPv4 datagrams addressed to us. Handle IP fragmentation
663  * (fragments received in any order) and ICMP at this level.
664  *
665  * Note that because our network is serviced by polling when we expect
666  * something (upon a referenced socket), we don't go through the work of
667  * locating the appropriate socket a datagram is destined for. We'll only
668  * accept data for the referenced socket. This means we don't have
669  * asynchronous networking, but since we can't service the net using an
670  * interrupt handler, it doesn't do us any good to try to service datagrams
671  * destined for sockets other than the referenced one. Data is handled in
672  * a fifo manner.
673  *
674  * The mac layer will grab all frames for us. If we find we don't have all
675  * the necessary fragments to reassemble the datagram, we'll call the mac
676  * layer again for FRAG_ATTEMPTS to see if it has any more frames.
677  *
678  * Supported protocols: IPPROTO_IP, IPPROTO_ICMP, IPPROTO_UDP.
679  *
680  * Returns: number of NETWORK_LVL datagrams placed on socket , -1 if error
681  * occurred.
682  *
683  * Note: errno is set to ETIMEDOUT if fragment reassembly fails.
684  */
685 int
686 ipv4_input(int index)
687 {
688 	int			datagrams = 0;
689 	int			frag_stat, input_attempts = 0;
690 	uint16_t		iphlen, iplen, ip_id;
691 	int16_t			curr_off;
692 	struct ip		*iphp;
693 	struct inetgram		*igp, *newgp = NULL, *ipv4_listp = NULL;
694 	struct in_addr		ipdst, ipsrc;
695 	mblk_t			*mp;
696 	enum SockType		type;
697 
698 #ifdef	DEBUG
699 	printf("ipv4_input(%d): start ######################################\n",
700 	    index);
701 #endif	/* DEBUG */
702 
703 	frag_flush();
704 
705 ipv4_try_again:
706 
707 	while ((igp = sockets[index].inq) != NULL) {
708 		if (igp->igm_level != NETWORK_LVL) {
709 #ifdef	DEBUG
710 			printf("ipv4_input(%d): unexpected frame type: %d\n",
711 			    index, igp->igm_level);
712 #endif	/* DEBUG */
713 			del_gram(&sockets[index].inq, igp, TRUE);
714 			continue;
715 		}
716 		iphp = (struct ip *)igp->igm_mp->b_rptr;
717 		if (iphp->ip_v != IPVERSION) {
718 			dprintf("ipv4_input(%d): IPv%d datagram discarded\n",
719 			index, iphp->ip_v);
720 			del_gram(&sockets[index].inq, igp, TRUE);
721 			continue;
722 		}
723 		iphlen = iphp->ip_hl << 2;
724 		if (iphlen < sizeof (struct ip)) {
725 			dprintf("ipv4_input(%d): IP msg too short (%d < %u)\n",
726 			    index, iphlen, (uint_t)sizeof (struct ip));
727 			del_gram(&sockets[index].inq, igp, TRUE);
728 			continue;
729 		}
730 		iplen = ntohs(iphp->ip_len);
731 		if (iplen > msgdsize(igp->igm_mp)) {
732 			dprintf("ipv4_input(%d): IP len/buffer mismatch "
733 			    "(%d > %lu)\n", index, iplen, igp->igm_mp->b_size);
734 			del_gram(&sockets[index].inq, igp, TRUE);
735 			continue;
736 		}
737 
738 		bcopy((caddr_t)&(iphp->ip_dst), (caddr_t)&ipdst,
739 		    sizeof (ipdst));
740 		bcopy((caddr_t)&(iphp->ip_src), (caddr_t)&ipsrc,
741 		    sizeof (ipsrc));
742 
743 		/* igp->igm_mp->b_datap is guaranteed to be 64 bit aligned] */
744 		if (ipv4cksum((uint16_t *)iphp, iphlen) != 0) {
745 			dprintf("ipv4_input(%d): Bad IP header checksum "
746 			    "(to %s)\n", index, inet_ntoa(ipdst));
747 			del_gram(&sockets[index].inq, igp, TRUE);
748 			continue;
749 		}
750 
751 		if (!promiscuous) {
752 			/* validate destination address */
753 			if (ipdst.s_addr != htonl(INADDR_BROADCAST) &&
754 			    ipdst.s_addr != (mynet.s_addr | ~netmask.s_addr) &&
755 			    ipdst.s_addr != myip.s_addr) {
756 #ifdef	DEBUG
757 				printf("ipv4_input(%d): msg to %s discarded.\n",
758 				    index, inet_ntoa(ipdst));
759 #endif	/* DEBUG */
760 				/* not ours */
761 				del_gram(&sockets[index].inq, igp, TRUE);
762 				continue;
763 			}
764 		}
765 
766 		/* Intercept ICMP first */
767 		if (!promiscuous && (iphp->ip_p == IPPROTO_ICMP)) {
768 			icmp4(igp, iphp, iphlen, ipsrc);
769 			del_gram(&sockets[index].inq, igp, TRUE);
770 			continue;
771 		}
772 
773 #ifdef	DEBUG
774 		printf("ipv4_input(%d): processing ID: 0x%x protocol %d "
775 		    "(0x%x) (0x%x,%d)\n",
776 		    index, ntohs(iphp->ip_id), iphp->ip_p, igp, igp->igm_mp,
777 		    igp->igm_mp->b_size);
778 #endif	/* DEBUG */
779 		type = sockets[index].type;
780 		if (type == INETBOOT_RAW) {
781 			/* No fragmentation - Just the raw packet. */
782 #ifdef	DEBUG
783 			printf("ipv4_input(%d): Raw packet.\n", index);
784 #endif	/* DEBUG */
785 			del_gram(&sockets[index].inq, igp, FALSE);
786 			add_grams(&ipv4_listp, igp);
787 			igp->igm_mp->b_rptr += iphlen;
788 			igp->igm_mp->b_wptr = igp->igm_mp->b_rptr + iplen;
789 			datagrams++;
790 			continue;
791 		}
792 
793 		if ((type == INETBOOT_DGRAM && iphp->ip_p != IPPROTO_UDP) ||
794 		    (type == INETBOOT_STREAM && iphp->ip_p != IPPROTO_TCP)) {
795 			/* Wrong protocol. */
796 			dprintf("ipv4_input(%d): unexpected protocol: "
797 			    "%d for socket type %d\n", index, iphp->ip_p, type);
798 			del_gram(&sockets[index].inq, igp, TRUE);
799 			continue;
800 		}
801 
802 		/*
803 		 * The following code is common to both STREAM and DATAGRAM
804 		 * sockets.
805 		 */
806 
807 		/*
808 		 * Once we process the first fragment, we won't have
809 		 * the transport header, so we'll have to  match on
810 		 * IP id.
811 		 */
812 		curr_off = ntohs(iphp->ip_off);
813 		if ((curr_off & ~(IP_DF | IP_MF)) == 0) {
814 			uint16_t	*transp;
815 
816 			/* Validate transport header. */
817 			mp = igp->igm_mp;
818 			if ((mp->b_wptr - mp->b_rptr - iphlen) <
819 			    sockets[index].headerlen[TRANSPORT_LVL](igp)) {
820 				dprintf("ipv4_input(%d): datagram 0 "
821 				    "too small to hold transport header "
822 				    "(from %s)\n", index, inet_ntoa(ipsrc));
823 				del_gram(&sockets[index].inq, igp, TRUE);
824 				continue;
825 			}
826 
827 			/*
828 			 * check alignment - transport elements are 16
829 			 * bit aligned..
830 			 */
831 			transp = (uint16_t *)(mp->b_rptr + iphlen);
832 			if ((uintptr_t)transp % sizeof (uint16_t)) {
833 				dprintf("ipv4_input(%d): Transport "
834 				    "header is not 16-bit aligned "
835 				    "(0x%lx, from %s)\n", index, (long)transp,
836 				    inet_ntoa(ipsrc));
837 				del_gram(&sockets[index].inq, igp, TRUE);
838 				continue;
839 			}
840 
841 			if (curr_off & IP_MF) {
842 				/* fragment 0 of fragmented datagram */
843 				ip_id = ntohs(iphp->ip_id);
844 				frag_stat = frag_add(curr_off, igp->igm_mp,
845 				    ip_id, iplen, iphlen, iphp->ip_p);
846 				if (frag_stat != FRAG_SUCCESS) {
847 #ifdef	FRAG_DEBUG
848 					if (frag_stat == FRAG_DUP) {
849 						printf("ipv4_input"
850 						    "(%d): Frag dup.\n", index);
851 					} else {
852 						printf("ipv4_input"
853 						    "(%d): too many "
854 						    "frags\n", index);
855 					}
856 #endif	/* FRAG_DEBUG */
857 					del_gram(&sockets[index].inq,
858 					    igp, TRUE);
859 					continue;
860 				}
861 
862 				del_gram(&sockets[index].inq, igp, FALSE);
863 				/* keep the data, lose the inetgram */
864 				bkmem_free((caddr_t)igp,
865 				    sizeof (struct inetgram));
866 #ifdef	FRAG_DEBUG
867 				printf("ipv4_input(%d): Frag/Off/Id "
868 				    "(%d/%d/%x)\n", index, fragments,
869 				    IPV4_OFFSET(curr_off), ip_id);
870 #endif	/* FRAG_DEBUG */
871 			} else {
872 				/* Single, unfragmented datagram */
873 				newgp = make_trans_datagram(index, igp,
874 				    ipsrc, ipdst, iphlen);
875 				if (newgp != NULL) {
876 					add_grams(&ipv4_listp, newgp);
877 					datagrams++;
878 				}
879 				del_gram(&sockets[index].inq, igp,
880 				    TRUE);
881 				continue;
882 			}
883 		} else {
884 			/* fragments other than 0 */
885 			frag_stat = frag_add(curr_off, igp->igm_mp,
886 			    ntohs(iphp->ip_id), iplen, iphlen, iphp->ip_p);
887 
888 			if (frag_stat == FRAG_SUCCESS) {
889 #ifdef	FRAG_DEBUG
890 				printf("ipv4_input(%d): Frag(%d) "
891 				    "off(%d) id(%x)\n", index,
892 				    fragments, IPV4_OFFSET(curr_off),
893 				    ntohs(iphp->ip_id));
894 #endif	/* FRAG_DEBUG */
895 				del_gram(&sockets[index].inq, igp, FALSE);
896 				/* keep the data, lose the inetgram */
897 				bkmem_free((caddr_t)igp,
898 				    sizeof (struct inetgram));
899 			} else {
900 #ifdef	FRAG_DEBUG
901 				if (frag_stat == FRAG_DUP)
902 					printf("ipv4_input(%d): Frag "
903 					    "dup.\n", index);
904 				else {
905 					printf("ipv4_input(%d): too "
906 					    "many frags\n", index);
907 				}
908 #endif	/* FRAG_DEBUG */
909 				del_gram(&sockets[index].inq, igp, TRUE);
910 				continue;
911 			}
912 		}
913 
914 		/*
915 		 * Determine if we have all of the fragments.
916 		 *
917 		 * NOTE: at this point, we've placed the data in the
918 		 * fragment table, and the inetgram (igp) has been
919 		 * deleted.
920 		 */
921 		if (!frag_chk())
922 			continue;
923 
924 		newgp = make_trans_datagram(index, NULL, ipsrc, ipdst, iphlen);
925 		if (newgp == NULL)
926 			continue;
927 		add_grams(&ipv4_listp, newgp);
928 		datagrams++;
929 	}
930 	if (ipv4_listp == NULL && fragments != 0) {
931 		if (++input_attempts > FRAG_ATTEMPTS) {
932 			dprintf("ipv4_input(%d): reassembly(%d) timed out in "
933 			    "%d msecs.\n", index, fragments,
934 			    sockets[index].in_timeout * input_attempts);
935 			frag_flush();
936 			errno = ETIMEDOUT;
937 			return (-1);
938 		} else {
939 			/*
940 			 * Call the media layer again... there may be more
941 			 * packets waiting.
942 			 */
943 			if (sockets[index].input[MEDIA_LVL](index) < 0) {
944 				/* errno will be set appropriately */
945 				frag_flush();
946 				return (-1);
947 			}
948 			goto ipv4_try_again;
949 		}
950 	}
951 
952 	add_grams(&sockets[index].inq, ipv4_listp);
953 
954 	return (datagrams);
955 }
956 
957 /*
958  * ipv4_output: Generate IPv4 datagram(s) for the payload and deliver them.
959  * Routing is handled here as well, by reusing the saddr field to hold the
960  * router's IP address.
961  *
962  * We don't deal with fragmentation on the outgoing side.
963  *
964  * Arguments: index to socket, inetgram to send.
965  *
966  * Returns: 0 for success, -1 if error occurred.
967  */
968 int
969 ipv4_output(int index, struct inetgram *ogp)
970 {
971 	struct ip	*iphp;
972 	uint64_t	iphbuffer[sizeof (struct ip)];
973 
974 #ifdef	DEBUG
975 	printf("ipv4_output(%d): size %d\n", index,
976 	    ogp->igm_mp->b_wptr - ogp->igm_mp->b_rptr);
977 #endif	/* DEBUG */
978 
979 	/* we don't deal (yet) with fragmentation. Maybe never will */
980 	if ((ogp->igm_mp->b_wptr - ogp->igm_mp->b_rptr) > mac_get_mtu()) {
981 		dprintf("ipv4: datagram too big for MAC layer.\n");
982 		errno = E2BIG;
983 		return (-1);
984 	}
985 
986 	if (ogp->igm_level != NETWORK_LVL) {
987 #ifdef	DEBUG
988 		printf("ipv4_output(%d): unexpected frame type: %d\n", index,
989 		    ogp->igm_level);
990 #endif	/* DEBUG */
991 		errno = EINVAL;
992 		return (-1);
993 	}
994 
995 	if (sockets[index].out_flags & SO_DONTROUTE)
996 		ogp->igm_oflags |= MSG_DONTROUTE;
997 
998 	iphp = (struct ip *)&iphbuffer;
999 	iphp->ip_v = IPVERSION;
1000 	iphp->ip_hl = sizeof (struct ip) / 4;
1001 	iphp->ip_tos = 0;
1002 	iphp->ip_len = htons(ogp->igm_mp->b_wptr - ogp->igm_mp->b_rptr +
1003 	    sizeof (struct ip));
1004 	iphp->ip_id = htons(++g_ip_id);
1005 	iphp->ip_off = htons(IP_DF);
1006 	iphp->ip_p = sockets[index].proto;
1007 	iphp->ip_sum = htons(0);
1008 	iphp->ip_ttl = ttl;
1009 
1010 	/* struct copies */
1011 	iphp->ip_src = myip;
1012 	iphp->ip_dst = ogp->igm_saddr.sin_addr;
1013 
1014 	/*
1015 	 * On local / limited broadcasts, don't route. From a purist's
1016 	 * perspective, we should be setting the TTL to 1. But
1017 	 * operational experience has shown that some BOOTP relay agents
1018 	 * (ciscos) discard our packets. Furthermore, these devices also
1019 	 * *don't* reset the TTL to MAXTTL on the unicast side of the
1020 	 * BOOTP relay agent! Sigh. Thus to work correctly in these
1021 	 * environments, we leave the TTL as it has been been set by
1022 	 * the application layer, and simply don't check for a route.
1023 	 */
1024 	if (iphp->ip_dst.s_addr == htonl(INADDR_BROADCAST) ||
1025 	    (netmask.s_addr != htonl(INADDR_BROADCAST) &&
1026 	    iphp->ip_dst.s_addr == (mynet.s_addr | ~netmask.s_addr))) {
1027 		ogp->igm_oflags |= MSG_DONTROUTE;
1028 	}
1029 
1030 	/* Routing necessary? */
1031 	if ((ogp->igm_oflags & MSG_DONTROUTE) == 0 &&
1032 	    ((iphp->ip_dst.s_addr & netmask.s_addr) != mynet.s_addr)) {
1033 		struct in_addr *rip;
1034 		if ((rip = ipv4_get_route(RT_HOST, &iphp->ip_dst,
1035 		    NULL)) == NULL) {
1036 			rip = ipv4_get_route(RT_DEFAULT, NULL, NULL);
1037 		}
1038 		if (rip == NULL) {
1039 			dprintf("ipv4(%d): No route to %s.\n",
1040 			    index, inet_ntoa(iphp->ip_dst));
1041 			errno = EHOSTUNREACH;
1042 			return (-1);
1043 		}
1044 		ogp->igm_router.s_addr = rip->s_addr;
1045 	} else
1046 		ogp->igm_router.s_addr = htonl(INADDR_ANY);
1047 
1048 	iphp->ip_sum = ipv4cksum((uint16_t *)iphp, sizeof (struct ip));
1049 	ogp->igm_mp->b_rptr -= sizeof (struct ip);
1050 	bcopy((caddr_t)iphp, (caddr_t)(ogp->igm_mp->b_rptr),
1051 	    sizeof (struct ip));
1052 
1053 	ogp->igm_level = MEDIA_LVL;
1054 
1055 	return (0);
1056 }
1057 
1058 /*
1059  * Function to be called by TCP to send out a packet.  This is used
1060  * when TCP wants to send out packets which it has already filled in
1061  * most of the header fields.
1062  */
1063 int
1064 ipv4_tcp_output(int sock_id, mblk_t *pkt)
1065 {
1066 	struct ip *iph;
1067 	struct in_addr *rip = NULL;
1068 	struct inetgram datagram;
1069 
1070 	iph = (struct ip *)pkt->b_rptr;
1071 
1072 	bzero(&datagram, sizeof (struct inetgram));
1073 
1074 	/*
1075 	 * Bootparams doesn't know about subnet masks, so we need to
1076 	 * explicitly check for this flag.
1077 	 */
1078 	if (sockets[sock_id].out_flags & SO_DONTROUTE)
1079 		datagram.igm_oflags |= MSG_DONTROUTE;
1080 
1081 	/* Routing necessary? */
1082 	if (((datagram.igm_oflags & MSG_DONTROUTE) == 0) &&
1083 		((iph->ip_dst.s_addr & netmask.s_addr) != mynet.s_addr)) {
1084 		if ((rip = ipv4_get_route(RT_HOST, &iph->ip_dst,
1085 		    NULL)) == NULL) {
1086 			rip = ipv4_get_route(RT_DEFAULT, NULL, NULL);
1087 		}
1088 		if (rip == NULL) {
1089 			dprintf("ipv4(%d): No route to %s.\n",
1090 			    sock_id, inet_ntoa(iph->ip_dst));
1091 			errno = EHOSTUNREACH;
1092 			return (-1);
1093 		}
1094 	}
1095 
1096 	iph->ip_id = htons(++g_ip_id);
1097 	iph->ip_sum = ipv4cksum((uint16_t *)iph, sizeof (struct ip));
1098 #if DEBUG > 1
1099 	printf("ipv4_tcp_output: dump IP packet(%d)\n", iph->ip_len);
1100 	hexdump((char *)pkt->b_rptr, iph->ip_len);
1101 #endif
1102 	/* Call the MAC layer output routine to send it out. */
1103 	datagram.igm_mp = pkt;
1104 	datagram.igm_level = MEDIA_LVL;
1105 	if (rip != NULL)
1106 		datagram.igm_router.s_addr = rip->s_addr;
1107 	else
1108 		datagram.igm_router.s_addr = 0;
1109 	return (mac_state.mac_output(sock_id, &datagram));
1110 }
1111 
1112 /*
1113  * Internet address interpretation routine.
1114  * All the network library routines call this
1115  * routine to interpret entries in the data bases
1116  * which are expected to be an address.
1117  * The value returned is in network order.
1118  */
1119 in_addr_t
1120 inet_addr(const char *cp)
1121 {
1122 	uint32_t val, base, n;
1123 	char c;
1124 	uint32_t parts[4], *pp = parts;
1125 
1126 	if (*cp == '\0')
1127 		return ((uint32_t)-1); /* disallow null string in cp */
1128 again:
1129 	/*
1130 	 * Collect number up to ``.''.
1131 	 * Values are specified as for C:
1132 	 * 0x=hex, 0=octal, other=decimal.
1133 	 */
1134 	val = 0; base = 10;
1135 	if (*cp == '0') {
1136 		if (*++cp == 'x' || *cp == 'X')
1137 			base = 16, cp++;
1138 		else
1139 			base = 8;
1140 	}
1141 	while ((c = *cp) != '\0') {
1142 		if (isdigit(c)) {
1143 			if ((c - '0') >= base)
1144 			    break;
1145 			val = (val * base) + (c - '0');
1146 			cp++;
1147 			continue;
1148 		}
1149 		if (base == 16 && isxdigit(c)) {
1150 			val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
1151 			cp++;
1152 			continue;
1153 		}
1154 		break;
1155 	}
1156 	if (*cp == '.') {
1157 		/*
1158 		 * Internet format:
1159 		 *	a.b.c.d
1160 		 *	a.b.c	(with c treated as 16-bits)
1161 		 *	a.b	(with b treated as 24 bits)
1162 		 */
1163 		if ((pp >= parts + 3) || (val > 0xff)) {
1164 			return ((uint32_t)-1);
1165 		}
1166 		*pp++ = val, cp++;
1167 		goto again;
1168 	}
1169 	/*
1170 	 * Check for trailing characters.
1171 	 */
1172 	if (*cp && !isspace(*cp)) {
1173 		return ((uint32_t)-1);
1174 	}
1175 	*pp++ = val;
1176 	/*
1177 	 * Concoct the address according to
1178 	 * the number of parts specified.
1179 	 */
1180 	n = pp - parts;
1181 	switch (n) {
1182 
1183 	case 1:				/* a -- 32 bits */
1184 		val = parts[0];
1185 		break;
1186 
1187 	case 2:				/* a.b -- 8.24 bits */
1188 		if (parts[1] > 0xffffff)
1189 		    return ((uint32_t)-1);
1190 		val = (parts[0] << 24) | (parts[1] & 0xffffff);
1191 		break;
1192 
1193 	case 3:				/* a.b.c -- 8.8.16 bits */
1194 		if (parts[2] > 0xffff)
1195 		    return ((uint32_t)-1);
1196 		val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
1197 			(parts[2] & 0xffff);
1198 		break;
1199 
1200 	case 4:				/* a.b.c.d -- 8.8.8.8 bits */
1201 		if (parts[3] > 0xff)
1202 		    return ((uint32_t)-1);
1203 		val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
1204 		    ((parts[2] & 0xff) << 8) | (parts[3] & 0xff);
1205 		break;
1206 
1207 	default:
1208 		return ((uint32_t)-1);
1209 	}
1210 	val = htonl(val);
1211 	return (val);
1212 }
1213 
1214 void
1215 hexdump(char *data, int datalen)
1216 {
1217 	char *p;
1218 	ushort_t *p16 = (ushort_t *)data;
1219 	char *p8 = data;
1220 	int i, left, len;
1221 	int chunk = 16;  /* 16 bytes per line */
1222 
1223 	printf("\n");
1224 
1225 	for (p = data; p < data + datalen; p += chunk) {
1226 		printf("\t%4d: ", (int)(p - data));
1227 		left = (data + datalen) - p;
1228 		len = MIN(chunk, left);
1229 		for (i = 0; i < (len / 2); i++)
1230 			printf("%04x ", ntohs(*p16++) & 0xffff);
1231 		if (len % 2) {
1232 			printf("%02x   ", *((unsigned char *)p16));
1233 		}
1234 		for (i = 0; i < (chunk - left) / 2; i++)
1235 			printf("     ");
1236 
1237 		printf("   ");
1238 		for (i = 0; i < len; i++, p8++)
1239 			printf("%c", isprint(*p8) ? *p8 : '.');
1240 		printf("\n");
1241 	}
1242 
1243 	printf("\n");
1244 }
1245