238 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			238 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
| ip_lib.c
 | |
| 
 | |
| Copyright 1995 Philip Homburg
 | |
| */
 | |
| 
 | |
| #include "inet.h"
 | |
| #include "buf.h"
 | |
| #include "event.h"
 | |
| #include "type.h"
 | |
| 
 | |
| #include "assert.h"
 | |
| #include "io.h"
 | |
| #include "ip_int.h"
 | |
| 
 | |
| THIS_FILE
 | |
| 
 | |
| PUBLIC ipaddr_t ip_get_netmask (hostaddr)
 | |
| ipaddr_t hostaddr;
 | |
| {
 | |
| 	return ip_netmask(ip_nettype(hostaddr));
 | |
| }
 | |
| 
 | |
| PUBLIC int ip_chk_hdropt (opt, optlen)
 | |
| u8_t *opt;
 | |
| int optlen;
 | |
| {
 | |
| 	int i, security_present= FALSE, lose_source_present= FALSE,
 | |
| 		strict_source_present= FALSE, record_route_present= FALSE,
 | |
| 		timestamp_present= FALSE;
 | |
| 
 | |
| 	assert (!(optlen & 3));
 | |
| 	i= 0;
 | |
| 	while (i<optlen)
 | |
| 	{
 | |
| 		DBLOCK(2, printf("*opt= %d\n", *opt));
 | |
| 
 | |
| 		switch (*opt)
 | |
| 		{
 | |
| 		case IP_OPT_EOL:	/* End of Option list */
 | |
| 			return NW_OK;
 | |
| 		case IP_OPT_NOP:	/* No Operation */
 | |
| 			i++;
 | |
| 			opt++;
 | |
| 			break;
 | |
| 		case IP_OPT_SEC:	/* Security */
 | |
| 			if (security_present)
 | |
| 				return EINVAL;
 | |
| 			security_present= TRUE;
 | |
| 			if (opt[1] != 11)
 | |
| 				return EINVAL;
 | |
| 			i += opt[1];
 | |
| 			opt += opt[1];
 | |
| 			break;
 | |
| 		case IP_OPT_LSRR:	/* Lose Source and Record Route */
 | |
| 			if (lose_source_present)
 | |
| 			{
 | |
| 				DBLOCK(1, printf("2nd lose soruce route\n"));
 | |
| 				return EINVAL;
 | |
| 			}
 | |
| 			lose_source_present= TRUE;
 | |
| 			if (opt[1]<3)
 | |
| 			{
 | |
| 				DBLOCK(1,
 | |
| 				printf("wrong length in source route\n"));
 | |
| 				return EINVAL;
 | |
| 			}
 | |
| 			i += opt[1];
 | |
| 			opt += opt[1];
 | |
| 			break;
 | |
| 		case IP_OPT_SSRR:	/* Strict Source and Record Route */
 | |
| 			if (strict_source_present)
 | |
| 				return EINVAL;
 | |
| 			strict_source_present= TRUE;
 | |
| 			if (opt[1]<3)
 | |
| 				return EINVAL;
 | |
| 			i += opt[1];
 | |
| 			opt += opt[1];
 | |
| 			break;
 | |
| 		case IP_OPT_RR:		/* Record Route */
 | |
| 			if (record_route_present)
 | |
| 				return EINVAL;
 | |
| 			record_route_present= TRUE;
 | |
| 			if (opt[1]<3)
 | |
| 				return EINVAL;
 | |
| 			i += opt[1];
 | |
| 			opt += opt[1];
 | |
| 			break;
 | |
| 		case IP_OPT_TS:		/* Timestamp */
 | |
| 			if (timestamp_present)
 | |
| 				return EINVAL;
 | |
| 			timestamp_present= TRUE;
 | |
| 			if (opt[1] != 4)
 | |
| 				return EINVAL;
 | |
| 			switch (opt[3] & 0xff)
 | |
| 			{
 | |
| 			case 0:
 | |
| 			case 1:
 | |
| 			case 3:
 | |
| 				break;
 | |
| 			default:
 | |
| 				return EINVAL;
 | |
| 			}
 | |
| 			i += opt[1];
 | |
| 			opt += opt[1];
 | |
| 			break;
 | |
| 		case IP_OPT_RTRALT:
 | |
| 			if (opt[1] != 4)
 | |
| 				return EINVAL;
 | |
| 			i += opt[1];
 | |
| 			opt += opt[1];
 | |
| 			break;
 | |
| 		default:
 | |
| 			return EINVAL;
 | |
| 		}
 | |
| 	}
 | |
| 	if (i > optlen)
 | |
| 	{
 | |
| 		DBLOCK(1, printf("option of wrong length\n"));
 | |
| 		return EINVAL;
 | |
| 	}
 | |
| 	return NW_OK;
 | |
| }
 | |
| 
 | |
| PUBLIC void ip_print_frags(acc)
 | |
| acc_t *acc;
 | |
| {
 | |
| #if DEBUG
 | |
| 	ip_hdr_t *ip_hdr;
 | |
| 	int first;
 | |
| 
 | |
| 	if (!acc)
 | |
| 		printf("(null)");
 | |
| 
 | |
| 	for (first= 1; acc; acc= acc->acc_ext_link, first= 0)
 | |
| 	{
 | |
| assert (acc->acc_length >= IP_MIN_HDR_SIZE);
 | |
| 		ip_hdr= (ip_hdr_t *)ptr2acc_data(acc);
 | |
| 		if (first)
 | |
| 		{
 | |
| 			writeIpAddr(ip_hdr->ih_src);
 | |
| 			printf(" > ");
 | |
| 			writeIpAddr(ip_hdr->ih_dst);
 | |
| 		}
 | |
| 		printf(" {%x:%d@%d%c}", ntohs(ip_hdr->ih_id),
 | |
| 			ntohs(ip_hdr->ih_length), 
 | |
| 			(ntohs(ip_hdr->ih_flags_fragoff) & IH_FRAGOFF_MASK)*8,
 | |
| 			(ntohs(ip_hdr->ih_flags_fragoff) & IH_MORE_FRAGS) ?
 | |
| 			'+' : '\0');
 | |
| 	}
 | |
| #endif
 | |
| }
 | |
| 
 | |
| PUBLIC ipaddr_t ip_get_ifaddr(port_nr)
 | |
| int port_nr;
 | |
| {
 | |
| 	assert(port_nr >= 0 && port_nr < ip_conf_nr);
 | |
| 
 | |
| 	return ip_port_table[port_nr].ip_ipaddr;
 | |
| }
 | |
| 
 | |
| PUBLIC nettype_t ip_nettype(ipaddr)
 | |
| ipaddr_t ipaddr;
 | |
| {
 | |
| 	u8_t highbyte;
 | |
| 	nettype_t nettype;
 | |
| 
 | |
| 	ipaddr= ntohl(ipaddr);
 | |
| 	highbyte= (ipaddr >> 24) & 0xff;
 | |
| 	if (highbyte == 0)
 | |
| 	{
 | |
| 		if (ipaddr == 0)
 | |
| 			nettype= IPNT_ZERO;
 | |
| 		else
 | |
| 			nettype= IPNT_MARTIAN;
 | |
| 	}
 | |
| 	else if (highbyte < 127)
 | |
| 		nettype= IPNT_CLASS_A;
 | |
| 	else if (highbyte == 127)
 | |
| 		nettype= IPNT_LOCAL;
 | |
| 	else if (highbyte < 192)
 | |
| 		nettype= IPNT_CLASS_B;
 | |
| 	else if (highbyte < 224)
 | |
| 		nettype= IPNT_CLASS_C;
 | |
| 	else if (highbyte < 240)
 | |
| 		nettype= IPNT_CLASS_D;
 | |
| 	else if (highbyte < 248)
 | |
| 		nettype= IPNT_CLASS_E;
 | |
| 	else if (highbyte < 255)
 | |
| 		nettype= IPNT_MARTIAN;
 | |
| 	else
 | |
| 	{
 | |
| 		if (ipaddr == (ipaddr_t)-1)
 | |
| 			nettype= IPNT_BROADCAST;
 | |
| 		else
 | |
| 			nettype= IPNT_MARTIAN;
 | |
| 	}
 | |
| 	return nettype;
 | |
| }
 | |
| 
 | |
| PUBLIC ipaddr_t ip_netmask(nettype)
 | |
| nettype_t nettype;
 | |
| {
 | |
| 	switch(nettype)
 | |
| 	{
 | |
| 	case IPNT_ZERO:		return HTONL(0x00000000);
 | |
| 	case IPNT_CLASS_A:
 | |
| 	case IPNT_LOCAL:	return HTONL(0xff000000);
 | |
| 	case IPNT_CLASS_B:	return HTONL(0xffff0000);
 | |
| 	case IPNT_CLASS_C:	return HTONL(0xffffff00);
 | |
| 	default:		return HTONL(0xffffffff);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| #if 0
 | |
| PUBLIC char *ip_nettoa(nettype)
 | |
| nettype_t nettype;
 | |
| {
 | |
| 	switch(nettype)
 | |
| 	{
 | |
| 	case IPNT_ZERO:		return "zero";
 | |
| 	case IPNT_CLASS_A:	return "class A";
 | |
| 	case IPNT_LOCAL:	return "local";
 | |
| 	case IPNT_CLASS_B:	return "class B";
 | |
| 	case IPNT_CLASS_C:	return "class C";
 | |
| 	case IPNT_CLASS_D:	return "class D";
 | |
| 	case IPNT_CLASS_E:	return "class E";
 | |
| 	case IPNT_MARTIAN:	return "martian";
 | |
| 	case IPNT_BROADCAST:	return "broadcast";
 | |
| 	default:		return "<unknown>";
 | |
| 	}
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /*
 | |
|  * $PchId: ip_lib.c,v 1.10 2002/06/08 21:35:52 philip Exp $
 | |
|  */
 | 
