/*
 *  inet.c,v 1.59 1994/02/06 19:21:35 jch Exp
 */

/* Gated Release 3.5 */
/* Copyright (c) 1990,1991,1992,1993,1994 by Cornell University. All rights */
/* reserved. Refer to Particulars and other Copyright notices at the end of this */
/* file. */


#define	INCLUDE_IF
#include "include.h"
#include "inet.h"

int inet_ipforwarding = TRUE;		/* IP forwarding engine enabled */
int inet_udpcksum = TRUE;		/* UDP checksums enabled */

static task *inet_task;

const bits inet_proto_bits[] = {
#ifdef	IPPROTO_ICMP
    { IPPROTO_ICMP,	"icmp" },
#endif	/* IPPROTO_ICMP */
#ifdef	IPPROTO_IGMP    
    { IPPROTO_IGMP,	"igmp" },
#endif	/* IPPROTO_IGMP */
#ifdef	IPPROTO_GGP    
    { IPPROTO_GGP,	"ggp" },
#endif	/* IPPROTO_GGP */
#ifdef	IPPROTO_TCP    
    { IPPROTO_TCP,	"tcp" },
#endif	/* IPPROTO_TCP */
#ifdef	IPPROTO_EGP    
    { IPPROTO_EGP,	"egp" },
#endif	/* IPPROTO_EGP */
#ifdef	IPPROTO_UDP    
    { IPPROTO_UDP,	"udp" },
#endif	/* IPPROTO_UDP */
#ifdef	IPPROTO_OSPF    
    { IPPROTO_OSPF,	"ospf" },
#endif	/* IPPROTO_OSPF */
    { 0,		NULL }
} ;


#ifdef	IP_MULTICAST
#define	INET_IFPS_ALLROUTERS	IFPS_KEEP1	/* We joined the all-routers group on this interface */

static sockaddr_un *inet_addr_allrouters;	/* All routers multicast address */

#define	INET_ADDR_ALLROUTERS	0xe0000002	/* 224.0.0.2 */

static const bits inet_if_bits[] = {
    { INET_IFPS_ALLROUTERS, "AllRouters" },
    { 0 }
};
#endif	/* IP_MULTICAST */

sockaddr_un *inet_masks[34] = { 0 };
byte inet_mask_list[SOCKADDR_IN_LEN * (sizeof (struct in_addr) * NBBY + 1)];

sockaddr_un *inet_addr_default = 0;
sockaddr_un *inet_addr_loopback = 0;
sockaddr_un *inet_addr_any = 0;
sockaddr_un *inet_addr_reject = 0;		/* Where reject routes need to point */
sockaddr_un *inet_addr_blackhole = 0;		/* Where unreachable routes need to point */

/* Table for quick classification of networks */
struct inet_class inet_classes[256] = {

    /* Class A */

    { INET_CLASSC_A,	INET_CLASSF_NETWORK|INET_CLASSF_DEFAULT,	INET_MASK_DEFAULT },	/* 0 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 1 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 2 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 3 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 4 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 5 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 6 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 7 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 8 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 9 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 10 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 11 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 12 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 13 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 14 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 15 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 16 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 17 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 18 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 19 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 20 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 21 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 22 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 23 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 24 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 25 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 26 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 27 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 28 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 29 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 30 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 31 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 32 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 33 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 34 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 35 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 36 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 37 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 38 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 39 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 40 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 41 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 42 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 43 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 44 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 45 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 46 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 47 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 48 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 49 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 50 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 51 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 52 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 53 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 54 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 55 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 56 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 57 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 58 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 59 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 60 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 61 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 62 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 63 */
#ifdef	INET_CLASS_A_SHARP

    /* Class A# */

    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 64 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 65 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 66 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 67 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 68 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 69 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 70 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 71 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 72 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 73 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 74 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 75 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 76 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 77 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 78 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 79 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 80 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 81 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 82 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 83 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 84 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 85 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 86 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 87 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 88 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 89 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 90 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 91 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 92 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 93 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 94 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 95 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 96 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 97 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 98 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 99 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 100 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 101 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 102 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 103 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 104 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 105 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 106 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 107 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 108 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 109 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 110 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 111 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 112 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 113 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 114 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 115 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 116 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 117 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 118 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 119 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 120 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 121 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 122 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 123 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 124 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 125 */
    { INET_CLASSC_A_SHARP,	INET_CLASSF_EXPERIMENTAL,	INET_MASK_INVALID },	/* 126 */

#else	/* INET_CLASS_A_SHARP */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 64 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 65 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 66 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 67 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 68 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 69 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 70 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 71 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 72 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 73 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 74 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 75 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 76 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 77 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 78 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 79 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 80 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 81 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 82 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 83 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 84 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 85 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 86 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 87 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 88 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 89 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 90 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 91 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 92 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 93 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 94 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 95 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 96 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 97 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 98 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 99 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 100 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 101 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 102 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 103 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 104 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 105 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 106 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 107 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 108 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 109 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 110 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 111 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 112 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 113 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 114 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 115 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 116 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 117 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 118 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 119 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 120 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 121 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 122 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 123 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 124 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 125 */
    { INET_CLASSC_A,	INET_CLASSF_NETWORK,	INET_MASK_CLASSA },	/* 126 */
#endif	/* INET_CLASS_A_SHARP */
    { INET_CLASSC_A,	INET_CLASSF_LOOPBACK,	INET_MASK_CLASSA },	/* 127 */

    /* Class B */

    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 128-128.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 129-129.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 130-130.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 131-131.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 132-132.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 133-133.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 134-134.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 135-135.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 136-136.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 137-137.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 138-138.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 139-139.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 140-140.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 141-141.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 142-142.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 143-143.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 144-144.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 145-145.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 146-146.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 147-147.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 148-148.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 149-149.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 150-150.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 151-151.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 152-152.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 153-153.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 154-154.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 155-155.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 156-156.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 157-157.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 158-158.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 159-159.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 160-160.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 161-161.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 162-162.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 163-163.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 164-164.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 165-165.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 166-166.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 167-167.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 168-168.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 169-169.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 170-170.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 171-171.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 172-172.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 173-173.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 174-174.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 175-175.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 176-176.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 177-177.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 178-178.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 179-179.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 180-180.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 181-181.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 182-182.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 183-183.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 184-184.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 185-185.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 186-186.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 187-187.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 188-188.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 189-189.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 190-190.255 */
    { INET_CLASSC_B,	INET_CLASSF_NETWORK,	INET_MASK_CLASSB },	/* 191-191.255 */

    /* Class C */
    
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 192.0.0-192.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 193.0.0-193.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 194.0.0-194.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 195.0.0-195.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 196.0.0-196.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 197.0.0-197.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 198.0.0-198.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 199.0.0-199.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 200.0.0-200.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 201.0.0-201.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 202.0.0-202.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 203.0.0-203.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 204.0.0-204.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 205.0.0-205.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 206.0.0-206.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 207.0.0-207.255.255 */
#ifdef	INET_CLASS_C_SHARP

    /* Class C Sharp */

    { INET_CLASSC_C_SHARP,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC_SHARP },	/* 208.0.0-208.255.255 */
    { INET_CLASSC_C_SHARP,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC_SHARP },	/* 209.0.0-209.255.255 */
    { INET_CLASSC_C_SHARP,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC_SHARP },	/* 210.0.0-210.255.255 */
    { INET_CLASSC_C_SHARP,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC_SHARP },	/* 211.0.0-211.255.255 */
    { INET_CLASSC_C_SHARP,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC_SHARP },	/* 212.0.0-212.255.255 */
    { INET_CLASSC_C_SHARP,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC_SHARP },	/* 213.0.0-213.255.255 */
    { INET_CLASSC_C_SHARP,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC_SHARP },	/* 214.0.0-214.255.255 */
    { INET_CLASSC_C_SHARP,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC_SHARP },	/* 215.0.0-215.255.255 */
    { INET_CLASSC_C_SHARP,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC_SHARP },	/* 216.0.0-216.255.255 */
    { INET_CLASSC_C_SHARP,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC_SHARP },	/* 217.0.0-217.255.255 */
    { INET_CLASSC_C_SHARP,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC_SHARP },	/* 218.0.0-218.255.255 */
    { INET_CLASSC_C_SHARP,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC_SHARP },	/* 219.0.0-219.255.255 */
    { INET_CLASSC_C_SHARP,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC_SHARP },	/* 220.0.0-220.255.255 */
    { INET_CLASSC_C_SHARP,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC_SHARP },	/* 221.0.0-221.255.255 */
    { INET_CLASSC_C_SHARP,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC_SHARP },	/* 222.0.0-222.255.255 */
    { INET_CLASSC_C_SHARP,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC_SHARP },	/* 223.0.0-223.255.255 */
#else	/* INET_CLASS_C_SHARP */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 208.0.0-208.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 209.0.0-209.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 210.0.0-210.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 211.0.0-211.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 212.0.0-212.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 213.0.0-213.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 214.0.0-214.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 215.0.0-215.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 216.0.0-216.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 217.0.0-217.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 218.0.0-218.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 219.0.0-219.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 220.0.0-220.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 221.0.0-221.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 222.0.0-222.255.255 */
    { INET_CLASSC_C,	INET_CLASSF_NETWORK,	INET_MASK_CLASSC },	/* 223.0.0-223.255.255 */
#endif	/* INET_CLASS_C_SHARP */

    /* Class D (Multicast) */

    { INET_CLASSC_D,	INET_CLASSF_MULTICAST,	INET_MASK_CLASSD },	/* 224.0.0.0-224.255.255.255 */
    { INET_CLASSC_D,	INET_CLASSF_MULTICAST,	INET_MASK_CLASSD },	/* 225.0.0.0-225.255.255.255 */
    { INET_CLASSC_D,	INET_CLASSF_MULTICAST,	INET_MASK_CLASSD },	/* 226.0.0.0-226.255.255.255 */
    { INET_CLASSC_D,	INET_CLASSF_MULTICAST,	INET_MASK_CLASSD },	/* 227.0.0.0-227.255.255.255 */
    { INET_CLASSC_D,	INET_CLASSF_MULTICAST,	INET_MASK_CLASSD },	/* 228.0.0.0-228.255.255.255 */
    { INET_CLASSC_D,	INET_CLASSF_MULTICAST,	INET_MASK_CLASSD },	/* 229.0.0.0-229.255.255.255 */
    { INET_CLASSC_D,	INET_CLASSF_MULTICAST,	INET_MASK_CLASSD },	/* 230.0.0.0-230.255.255.255 */
    { INET_CLASSC_D,	INET_CLASSF_MULTICAST,	INET_MASK_CLASSD },	/* 231.0.0.0-231.255.255.255 */
    { INET_CLASSC_D,	INET_CLASSF_MULTICAST,	INET_MASK_CLASSD },	/* 232.0.0.0-232.255.255.255 */
    { INET_CLASSC_D,	INET_CLASSF_MULTICAST,	INET_MASK_CLASSD },	/* 233.0.0.0-233.255.255.255 */
    { INET_CLASSC_D,	INET_CLASSF_MULTICAST,	INET_MASK_CLASSD },	/* 234.0.0.0-234.255.255.255 */
    { INET_CLASSC_D,	INET_CLASSF_MULTICAST,	INET_MASK_CLASSD },	/* 235.0.0.0-235.255.255.255 */
    { INET_CLASSC_D,	INET_CLASSF_MULTICAST,	INET_MASK_CLASSD },	/* 236.0.0.0-236.255.255.255 */
    { INET_CLASSC_D,	INET_CLASSF_MULTICAST,	INET_MASK_CLASSD },	/* 237.0.0.0-237.255.255.255 */
    { INET_CLASSC_D,	INET_CLASSF_MULTICAST,	INET_MASK_CLASSD },	/* 238.0.0.0-238.255.255.255 */
    { INET_CLASSC_D,	INET_CLASSF_MULTICAST,	INET_MASK_CLASSD },	/* 239.0.0.0-239.255.255.255 */

#ifdef	INET_CLASS_E

    /* Class E */

    { INET_CLASSC_E,	INET_CLASSF_NETWORK,	INET_MASK_CLASSE },	/* 240.0.0-240.255.255.240 */
    { INET_CLASSC_E,	INET_CLASSF_NETWORK,	INET_MASK_CLASSE },	/* 241.0.0-241.255.255.240 */
    { INET_CLASSC_E,	INET_CLASSF_NETWORK,	INET_MASK_CLASSE },	/* 242.0.0-242.255.255.240 */
    { INET_CLASSC_E,	INET_CLASSF_NETWORK,	INET_MASK_CLASSE },	/* 243.0.0-243.255.255.240 */
    { INET_CLASSC_E,	INET_CLASSF_NETWORK,	INET_MASK_CLASSE },	/* 244.0.0-244.255.255.240 */
    { INET_CLASSC_E,	INET_CLASSF_NETWORK,	INET_MASK_CLASSE },	/* 245.0.0-245.255.255.240 */
    { INET_CLASSC_E,	INET_CLASSF_NETWORK,	INET_MASK_CLASSE },	/* 246.0.0-246.255.255.240 */
    { INET_CLASSC_E,	INET_CLASSF_NETWORK,	INET_MASK_CLASSE },	/* 247.0.0-247.255.255.240 */
    { INET_CLASSC_E,	INET_CLASSF_NETWORK,	INET_MASK_CLASSE },	/* 248.0.0-248.255.255.240 */
    { INET_CLASSC_E,	INET_CLASSF_NETWORK,	INET_MASK_CLASSE },	/* 249.0.0-249.255.255.240 */
    { INET_CLASSC_E,	INET_CLASSF_NETWORK,	INET_MASK_CLASSE },	/* 250.0.0-250.255.255.240 */
    { INET_CLASSC_E,	INET_CLASSF_NETWORK,	INET_MASK_CLASSE },	/* 251.0.0-251.255.255.240 */
    { INET_CLASSC_E,	INET_CLASSF_NETWORK,	INET_MASK_CLASSE },	/* 252.0.0-252.255.255.240 */
    { INET_CLASSC_E,	INET_CLASSF_NETWORK,	INET_MASK_CLASSE },	/* 253.0.0-253.255.255.240 */
    { INET_CLASSC_E,	INET_CLASSF_NETWORK,	INET_MASK_CLASSE },	/* 254.0.0-254.255.255.240 */
    { INET_CLASSC_E,	INET_CLASSF_NETWORK,	INET_MASK_CLASSE },	/* 255.0.0-255.255.255.240 */
#else	/* INET_CLASS_E */

    /* Reserved */
    
    { INET_CLASSC_RESERVED,	INET_CLASSF_RESERVED,	INET_MASK_INVALID },	/* 240.0.0-240.255.255.240 */
    { INET_CLASSC_RESERVED,	INET_CLASSF_RESERVED,	INET_MASK_INVALID },	/* 241.0.0-241.255.255.240 */
    { INET_CLASSC_RESERVED,	INET_CLASSF_RESERVED,	INET_MASK_INVALID },	/* 242.0.0-242.255.255.240 */
    { INET_CLASSC_RESERVED,	INET_CLASSF_RESERVED,	INET_MASK_INVALID },	/* 243.0.0-243.255.255.240 */
    { INET_CLASSC_RESERVED,	INET_CLASSF_RESERVED,	INET_MASK_INVALID },	/* 244.0.0-244.255.255.240 */
    { INET_CLASSC_RESERVED,	INET_CLASSF_RESERVED,	INET_MASK_INVALID },	/* 245.0.0-245.255.255.240 */
    { INET_CLASSC_RESERVED,	INET_CLASSF_RESERVED,	INET_MASK_INVALID },	/* 246.0.0-246.255.255.240 */
    { INET_CLASSC_RESERVED,	INET_CLASSF_RESERVED,	INET_MASK_INVALID },	/* 247.0.0-247.255.255.240 */
    { INET_CLASSC_RESERVED,	INET_CLASSF_RESERVED,	INET_MASK_INVALID },	/* 248.0.0-248.255.255.240 */
    { INET_CLASSC_RESERVED,	INET_CLASSF_RESERVED,	INET_MASK_INVALID },	/* 249.0.0-249.255.255.240 */
    { INET_CLASSC_RESERVED,	INET_CLASSF_RESERVED,	INET_MASK_INVALID },	/* 250.0.0-250.255.255.240 */
    { INET_CLASSC_RESERVED,	INET_CLASSF_RESERVED,	INET_MASK_INVALID },	/* 251.0.0-251.255.255.240 */
    { INET_CLASSC_RESERVED,	INET_CLASSF_RESERVED,	INET_MASK_INVALID },	/* 252.0.0-252.255.255.240 */
    { INET_CLASSC_RESERVED,	INET_CLASSF_RESERVED,	INET_MASK_INVALID },	/* 253.0.0-253.255.255.240 */
    { INET_CLASSC_RESERVED,	INET_CLASSF_RESERVED,	INET_MASK_INVALID },	/* 254.0.0-254.255.255.240 */
    { INET_CLASSC_RESERVED,	INET_CLASSF_RESERVED,	INET_MASK_INVALID },	/* 255.0.0-255.255.255.240 */
#endif	/* INET_CLASS_E */
} ;


struct martians {
    const char *dest;
    const char *mask;
    flag_t adv_flags;
    flag_t dm_flags;
};

static const struct martians inet_martians[] = {
    /* Do not allow anything on net 0 except the default */
    {	"0.0.0.0",		"0.0.0.0",		0,		DMF_EXACT },	/* Default */
    {	"0.0.0.0",		"255.0.0.0",		0,		0 },
	/* Do not allow anything on net 127 */
    {	"127.0.0.0",		"255.0.0.0",		ADVF_NO,	0	 },	/* Reserved */
	/* This are definately martians */
    {	"128.0.0.0",		"255.255.0.0",		ADVF_NO,	0	 },	/* Reserved */
    {	"191.255.0.0",		"255.255.0.0",		ADVF_NO,	0	 },	/* Reserved */
    {	"192.0.0.0",		"255.255.255.0",	ADVF_NO,	0	 },	/* Reserved */
    {	"223.255.255.0",	"255.255.255.0",	ADVF_NO,	0	 },	/* Reserved */
#ifdef	INET_CLASS_E
    {	"255.255.240.0",	"255.255.240.0",	ADVF_NO,	0	 },	/* Reserved */
#else	/* INET_CLASS_E */
    {	"240.0.0.0",		"240.0.0.0",		ADVF_NO,	0	 },	/* Reserved */
#endif /* INET_CLASS_E */
    {	NULL },
};


/* Optimized routine to locate an inet mask */
sockaddr_un *
inet_mask_locate __PF1(mask, u_int32)
{
    register sockaddr_un *mp;
	
    if (mask) {
	/* ffs returns the first bit set */
	register int i = ffs((int) ntohl(mask));
		
	if (i > 32 || mask != sock2ip(mp = inet_masks[33 - i])) {
	    /* Bogus mask or non contiguous */
	    mp = (sockaddr_un *) 0;
	}
    } else {
	/* The easy case */
	
	mp = inet_mask_default;
    }
	
    return mp;
}



/*
 * Return the mask for the given address, assumes fixed subnet mask from
 * the interface given.  Used by RIP and HELLO.
 */
sockaddr_un *
inet_mask_withif __PF3(addr, sockaddr_un *,
		       ifap, if_addr *,
		       state, flag_t *)
{
    int subnet = FALSE;
    register sockaddr_un *mask;
    sockaddr_un *natural_mask = inet_mask_natural(ifap->ifa_addr);
    
    /* Get the appropriate subnet mask for this destination */
    if (inet_net_natural(addr) == (sock2ip(natural_mask) & sock2ip(ifap->ifa_addr))
#ifndef	VARIABLE_MASKS
	/* BSD 4.3 and earlier assume the same subnet mask for all interfaces */
	|| (ifap == inet_ifwithnet(addr))
#else	/* VARIABLE_MASKS */
	/* If this is a supernet, subnets must be provided with masks */
	&& ifap->ifa_netmask > natural_mask
#endif	/* VARIABLE_MASKS */
	) {

	/* Same net, assume same subnet mask */
	if (ifap->ifa_netmask != natural_mask
	    && ifap->ifa_netmask != inet_mask_host) {
	    mask = ifap->ifa_netmask;
	    if (state) {
		/* Indicate subnet mask was derived */
		BIT_SET(*state, RTS_IFSUBNETMASK);
	    }
	} else {
	    mask = natural_mask;
	    subnet = state != 0;
	}
    } else {
	/* default to the natural mask */

	mask = inet_mask_natural(addr);
    }

    if (sock2ip(addr) & ~sock2ip(mask)) {
	/* Host route */

	mask = inet_mask_host;
	if (subnet) {
	    BIT_SET(*state, RTS_IFSUBNETMASK);
	}
    }

    return mask;
}



/*
 * Find interface on whole network of a possibly subnetted address.
 */
if_addr *
inet_ifwithnet __PF1(dstaddr, sockaddr_un *)
{
    register if_addr *ifap = (if_addr *) 0;

    IF_ADDR(ifap) {
	if (socktype(ifap->ifa_addr) == AF_INET
	    && ifap->ifa_net
	    && BIT_TEST(ifap->ifa_state, IFS_UP)
	    && inet_addrcmp_mask(sock2ip(dstaddr),
				 sock2ip(ifap->ifa_net),
				 sock2ip(inet_mask_natural(ifap->ifa_net)))) {
	    return ifap;
	}
    } IF_ADDR_END(ifap) ;

    return ifap;
}


#ifdef	IP_MULTICAST
/**/

/* Drop the all routers multicast group when we are not functioning as a router */
void
inet_allrouters_drop __PF1(ifap, if_addr *)
{
    if (BIT_TEST(ifap->ifa_ps[RTPROTO_INET].ips_state, INET_IFPS_ALLROUTERS)) {

	if (!BIT_TEST(task_state, TASKS_TEST)) {
	    /* Not in test mode, drop group membership */

	    (void) task_set_option(inet_task,
				   TASKOPTION_GROUP_DROP,
				   ifap,
				   inet_addr_allrouters);
	}

	/* Indicate now dropped */
	BIT_RESET(ifap->ifa_ps[RTPROTO_INET].ips_state, INET_IFPS_ALLROUTERS);
    }
}


/* Join the all routers multicast group when we are functioning as a router */
void
inet_allrouters_join __PF1(ifap, if_addr *)
{
    if (socktype(ifap->ifa_addr) == AF_INET &&
	BIT_TEST(ifap->ifa_state, IFS_MULTICAST)) {

	if (ifap->ifa_rtactive) {
	    if (!BIT_TEST(ifap->ifa_ps[RTPROTO_INET].ips_state, INET_IFPS_ALLROUTERS)) {
		/* Try to add to this multicast interface */

		if (BIT_TEST(task_state, TASKS_TEST)
		    || (!task_set_option(inet_task,
					 TASKOPTION_GROUP_ADD,
					 ifap,
					 inet_addr_allrouters)
			|| (errno == EADDRNOTAVAIL)
			|| (errno == EADDRINUSE))) {
		    /* Indicate we enabled it on this interface */

		    BIT_SET(ifap->ifa_ps[RTPROTO_INET].ips_state, INET_IFPS_ALLROUTERS);
		}
	    }
	} else {
	    /* Make sure we are not added on this interface */

	    inet_allrouters_drop(ifap);
	}
    }
}
#endif	/* IP_MULTICAST */

#ifdef	AUTONOMOUS_SYSTEM
/**/

as_t	inet_autonomous_system = 0;	/* Our autonomous system */

#endif	/* AUTONOMOUS_SYSTEM */

#ifdef	ROUTER_ID
/**/


if_addr_entry *inet_routerid_entry = 0;		/* Router ID */
static if_addr_entry *inet_routerid_config;	/* Requested Router ID */

/*
 *	Set the configured router_id
 */
int
inet_parse_routerid __PF2(addr, sockaddr_un *,
			  parse_error, char *)
{
    if (inet_routerid_config) {
	(void) sprintf(parse_error, "routerid specified twice");
	return TRUE;
    }

    if (is_martian(addr, inet_mask_host)) {
	(void) sprintf(parse_error, "address invalid for routerid");
	return TRUE;
    }

    inet_routerid_config = ifae_locate(addr, &if_local_list);

    return FALSE;
}


/*
 *	Select an initial routerID if possible
 */
static void
inet_routerid_select __PF0(void)
{
    if_addr *ifap = (if_addr *) 0;
    if_addr *ifap2;
	
    IF_ADDR(ifap2) {
    	if (!BIT_TEST(ifap2->ifa_state, IFS_UP)
	    || BIT_TEST(inet_class_flags(ifap2->ifa_addr_local),
			INET_CLASSF_LOOPBACK|INET_CLASSF_RESERVED|INET_CLASSF_DEFAULT)
	    || is_martian(ifap2->ifa_addr_local,
			  inet_mask_host)) {
	    /* Ignore down interfaces, loopback addresses and martians */
	    continue;
	}

	if (!ifap) {
	    /* First valid one */

	    ifap = ifap2;
	} else {
	    /* We already have one, is this one better? */

	    if (BIT_TEST(ifap2->ifa_state, IFS_LOOPBACK)
		&& !BIT_TEST(ifap->ifa_state, IFS_LOOPBACK)) {
		/* An address on the loopback interface is primo */

		ifap = ifap2;
	    }
	    if (BIT_TEST(ifap->ifa_state, IFS_POINTOPOINT)
		&& !BIT_TEST(ifap2->ifa_state, IFS_POINTOPOINT)) {
		/* A non-p2p address is prefered */

		ifap = ifap2;
	    }
	}
    } IF_ADDR_END(ifap2) ;

    if (ifap) {
	inet_routerid_entry = ifae_alloc(ifap->ifa_addrent_local);
    }
}


/*
 *	Notify what the router id is
 */
static inline void
inet_routerid_notify __PF0(void)
{
    if (inet_routerid_entry) {
	trace_only_tp(inet_task,
		      0,
		      ("inet_routerid_notify: Router ID: %A",
		       inet_routerid_entry->ifae_addr));
    } else {
	trace_only_tp(inet_task,
		      0,
		      ("inet_routerid_notify: No Router ID assigned"));
    }

    trace_only_tp(inet_task,
		  0,
		  (NULL));
}

static inline void
inet_routerid_reinit __PF0(void)
{
    if (inet_routerid_config
	&& inet_routerid_entry != inet_routerid_config) {
	/* Our current selection is no longer valid */

	if (inet_routerid_entry) {
	    ifae_free(inet_routerid_entry);
	}

	inet_routerid_entry = ifae_alloc(inet_routerid_config);
    }

    if (!inet_routerid_entry) {
	/* Try to make an initial selection now to keep the protocols happy */

	inet_routerid_select();
    }

    inet_routerid_notify();
}
#endif	/* ROUTER_ID */


/*
 *	Reinit
 */
static void
inet_reinit __PF1(tp, task *)
{
#ifdef	ROUTER_ID
    inet_routerid_reinit();
#endif	/* ROUTER_ID */

    SI_MARTIANS(AF_INET) = adv_destmask_finish(SI_MARTIANS(AF_INET));

    /* Install a static route reject route to net 127 */
    {
	adv_entry *intf_list = adv_alloc(ADVFT_IFAE|ADVF_FIRST, (proto_t) 0);
	sockaddr_un *addr = sockdup(inet_addr_loopback);

	sockmask(addr, inet_mask_classa);

	intf_list->adv_ifae = ifae_locate(inet_addr_loopback, &if_addr_list);

	(void) rt_parse_route(addr,
			      inet_mask_classa,
			      (adv_entry *) 0,
			      intf_list,
			      RTPREF_DIRECT,
			      RTS_REJECT|RTS_NOADVISE,
			      (char *) 0);

	sockfree(addr);
    }
}

#if	defined(ROUTER_ID)
/*
 *  Watch for interface changes to keep the router-ID up to date
 */
static void
inet_ifachange __PF2(tp, task *,
		     ifap, if_addr *)
{
#ifdef	ROUTER_ID
    int change = 0;
#endif	/* ROUTER_ID */
    
    if (socktype(ifap->ifa_addr) != AF_INET
	|| is_martian(ifap->ifa_addr_local,
		      inet_mask_host)) {
	/* Not valid for Router ID */

	return;
    }
    
    switch (ifap->ifa_change) {
    case IFC_NOCHANGE:
	/* Already chosen at reinit time */
	break;
	
    case IFC_ADD:
	if (BIT_TEST(ifap->ifa_state, IFS_UP)) {
	Up:
#ifdef	ROUTER_ID
	    Router_Up:
	    if (!inet_routerid_entry) {
		/* No Router ID, this must be the first valid interface */

		inet_routerid_entry = ifae_alloc(ifap->ifa_addrent_local);
		change++;
	    }
#endif	/* ROUTER_ID */
	}	
	break;

    case IFC_DELETE:
	/* Already down */
	break;
	
    case IFC_DELETE|IFC_UPDOWN:
    Down:
#ifdef	ROUTER_ID
    Router_Down:
	if (!inet_routerid_config
	    && ifap->ifa_addrent_local == inet_routerid_entry
	    && !inet_routerid_entry->ifae_n_if) {
	    /* Free this reference */

	    ifae_free(inet_routerid_entry);
	    inet_routerid_entry = (if_addr_entry *) 0;

	    /* Try to select a new one */
	    inet_routerid_select();

	    change++;
	}
#endif	/* ROUTER_ID */
	break;

    default:
	/* Something has changed */

	if (BIT_TEST(ifap->ifa_change, IFC_UPDOWN)) {
	    if (BIT_TEST(ifap->ifa_state, IFS_UP)) {
		goto Up;
	    } else {
		goto Down;
	    }
	}

	if (BIT_TEST(ifap->ifa_change, IFC_ADDR)) {
	    /* Local address change, see if it effects the routerID */

#ifdef	ROUTER_ID
	    if (!inet_routerid_entry) {
		/* No routerid, try to select this one */
		goto Router_Up;
	    }

	    /* See if our routerid went away */
	    goto Router_Down;
#endif	/* ROUTER_ID */
	}
	/* METRIC - We don't care */
	/* NETMASK - We don't care */
	/* BROADCAST - We don't care */
	/* MTU - We don't care */
	break;
    }

#ifdef	ROUTER_ID
    if (change) {
	inet_routerid_notify();
    }
#endif	/* ROUTER_ID */
}
#endif	/* defined(ROUTER_ID) */


static void
inet_dump __PF2(tp, task *,
		fp, FILE *)
{
    (void) fprintf(fp, "\tIP forwarding: %d\tUDP checksums: %d\n\n",
		   inet_ipforwarding,
		   inet_udpcksum);

    if (inet_addr_reject || inet_addr_blackhole) {
	if (inet_addr_reject) {
	    (void) fprintf(fp, "\tReject address: %A",
			   inet_addr_reject);
	}
	if (inet_addr_blackhole) {
	    (void) fprintf(fp, "\tBlackhole address: %A",
			   inet_addr_blackhole);
	}
	(void) fprintf(fp, "\n\n");
    }
#ifdef	AUTONOMOUS_SYSTEM
    /* Print our local ASes */
    if (inet_autonomous_system) {
	(void) fprintf(fp, "\tAutonomous system: %u\n",
		       inet_autonomous_system);

    }
#endif	/* AUTONOMOUS_SYSTEM */
    
#ifdef	ROUTER_ID
    if (inet_routerid_entry) {
	(void) fprintf(fp, "\tRouter ID: %A",
		       inet_routerid);

    (void) fprintf(fp, "\n\n");
    }
#endif	/* ROUTER_ID */

    /* Martians */
    (void) fprintf(fp, "\tMartians:\n");
    control_dmlist_dump(fp,
			2,
			SI_MARTIANS(AF_INET),
			(adv_entry *) 0,
			(adv_entry *) 0);
    (void) fprintf(fp, "\n");
}


/*
 *	Cleanup
 */
static void
inet_cleanup __PF1(tp, task *)
{
#ifdef	ROUTER_ID
    if (inet_routerid_config) {
	ifae_free(inet_routerid_config);
	inet_routerid_config = (if_addr_entry *) 0;
    }
#endif	/* ROUTER_ID */

    if (SI_MARTIANS(AF_INET)) {
	adv_free_list(SI_MARTIANS(AF_INET));

	SI_MARTIANS(AF_INET) = (adv_entry *) 0;
    }

    trace_freeup(tp->task_trace);
}


void
inet_var_init __PF0(void)
{
#ifdef	AUTONOMOUS_SYSTEM
    inet_autonomous_system = 0;
#endif	/* AUTONOMOUS_SYSTEM */
}


static void
inet_terminate __PF1(tp, task *)    
{
#ifdef	IP_MULTICAST
    if_addr *ifap;
	
    /* Leave the all routers multicast group */
    IF_ADDR(ifap) {
	if (BIT_TEST(ifap->ifa_state, IFS_UP)) {
	    inet_allrouters_drop(ifap);
	}
    } IF_ADDR_END(ifap) ;
#endif	/* IP_MULTICAST */

    inet_cleanup(tp);
    
    task_delete(tp);
}


void
inet_init __PF0(void)
{
    if (inet_task) {
	inet_task->task_trace = trace_set_global((bits *) 0, (flag_t) 0);
    } else {
	inet_task = task_alloc("INET",
			       TASKPRI_FAMILY,
			       trace_set_global((bits *) 0, (flag_t) 0));
	task_set_cleanup(inet_task, inet_cleanup);
#ifdef	ROUTER_ID
	task_set_ifachange(inet_task, inet_ifachange);
#endif	/* ROUTER_ID */
	task_set_reinit(inet_task, inet_reinit);
	task_set_terminate(inet_task, inet_terminate);
#ifdef	IP_MULTICAST
	inet_task->task_rtproto = RTPROTO_INET;
	inet_task->task_socket = task_get_socket(inet_task, PF_INET, SOCK_DGRAM, 0);
#endif	/* IP_MULTICAST */
	task_set_dump(inet_task, inet_dump);
	if (!task_create(inet_task)) {
	    task_quit(EINVAL);
	}
    }

    /* Verify the validity of some kernel variables */
    if (!BIT_TEST(task_state, TASKS_TEST)) {
	if (!inet_ipforwarding) {
	    trace_log_tp(inet_task,
			 0,
			 LOG_WARNING,
			 ("inet_init: *WARNING* IP forwarding disabled!"));
	}

	if (!inet_udpcksum) {
	    trace_log_tp(inet_task,
			 0,
			 LOG_WARNING,
			 ("inet_init: *WARNING* UDP checksums disabled in kernel"));
	}
    }

    /* Init martian list */
    {
	const struct martians *ptr = inet_martians;

	/* Build list of martian networks */
	do {
	    struct in_addr mask;
	    struct in_addr dest;

	    if (!inet_aton(ptr->dest, &dest) ||
		!inet_aton(ptr->mask, &mask)) {
		trace_log_tp(inet_task,
			     0,
			     LOG_WARNING,
			     ("inet_init: Invalid martian entry at %s/%s",
			      ptr->dest,
			      ptr->mask));
		continue;
	    }
	    martian_add(sockbuild_in(0, dest.s_addr),
			mask_locate(sockbuild_in(0, mask.s_addr)),
			ptr->adv_flags,
			ptr->dm_flags);
	} while ((++ptr)->dest) ;
    }

#ifdef	ROUTER_ID
    /* Try to choose a Router ID now */
    inet_routerid_reinit();
#endif	/* ROUTER_ID */

}


/*
 *	Init all kinds of inet structures
 */
void
inet_family_init __PF0(void)
{
    u_int32 mask = 0;
    sockaddr_un **mp = inet_masks;
    sockaddr_un *mpp = (sockaddr_un *) ((void_t) inet_mask_list);

    /* Build all possible contiguous masks */
    while (TRUE) {
	sockcopy(sockbuild_in(0, htonl(mask)), mpp);
	mask_insert(*mp++ = mpp);

	if (mask == INADDR_HOSTMASK) {
	    break;
	}
	mask = (mask >> 1) | 0x80000000l;
	mpp = (sockaddr_un *) ((void_t) ((byte *) mpp + SOCKADDR_IN_LEN));
    }
    
    sock_init_family(AF_INET,
		     (SOCKADDR_IN_LEN - sizeof (inet_addr_default->in.sin_addr)),
		     SOCKADDR_IN_LEN,
		     inet_mask_list,
		     sizeof inet_mask_list,
		     "sockaddr_un.in");

    /* Build useful addresses */
    inet_addr_default = sockdup(sockbuild_in(0, htonl(INADDR_DEFAULT)));
    inet_addr_any = sockdup(sockbuild_in(0, htonl(INADDR_ANY)));
    inet_addr_loopback = sockdup(sockbuild_in(0, htonl(INADDR_LOOPBACK)));

    rt_table_init_family(AF_INET);

#ifdef	IP_MULTICAST
    inet_addr_allrouters = sockdup(sockbuild_in(0, htonl(INET_ADDR_ALLROUTERS)));

    /* Set up interface bits to be printed */
    int_ps_bits[RTPROTO_INET] = inet_if_bits;
#endif	/* IP_MULTICAST */
}


/*
 * ------------------------------------------------------------------------
 * 
 * 	GateD, Release 3.5
 * 
 * 	Copyright (c) 1990,1991,1992,1993,1994 by Cornell University
 * 	    All rights reserved.
 * 
 * 	THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY
 * 	EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
 * 	LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * 	AND FITNESS FOR A PARTICULAR PURPOSE.
 * 
 * 	Royalty-free licenses to redistribute GateD Release
 * 	3 in whole or in part may be obtained by writing to:
 * 
 * 	    GateDaemon Project
 * 	    Information Technologies/Network Resources
 * 	    200 CCC
 * 	    Cornell University
 * 	    Ithaca, NY  14853-2601  USA
 * 
 * 	GateD is based on Kirton's EGP, UC Berkeley's routing
 * 	daemon	 (routed), and DCN's HELLO routing Protocol.
 * 	Development of GateD has been supported in part by the
 * 	National Science Foundation.
 * 
 * 	Please forward bug fixes, enhancements and questions to the
 * 	gated mailing list: gated-people@gated.cornell.edu.
 * 
 * ------------------------------------------------------------------------
 * 
 *       Portions of this software may fall under the following
 *       copyrights:
 * 
 * 	Copyright (c) 1988 Regents of the University of California.
 * 	All rights reserved.
 * 
 * 	Redistribution and use in source and binary forms are
 * 	permitted provided that the above copyright notice and
 * 	this paragraph are duplicated in all such forms and that
 * 	any documentation, advertising materials, and other
 * 	materials related to such distribution and use
 * 	acknowledge that the software was developed by the
 * 	University of California, Berkeley.  The name of the
 * 	University may not be used to endorse or promote
 * 	products derived from this software without specific
 * 	prior written permission.  THIS SOFTWARE IS PROVIDED
 * 	``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
 * 	INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * 	MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */
