/* * $Id: mrt.h,v 2.2 2000/05/23 08:02:12 masaki Exp $ */ #ifndef _MRT_H #define _MRT_H #define MAX_BGP_PEERS 64 #define MAX_BGP_VIEWS 64 #include #include #include #include #include #include #ifdef __GNUC__ /* to avoid it defined in stdio.h */ #include #else #ifndef NT #include #endif /* NT */ #endif /* __GNUC__ */ #include #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #ifndef NT #include #include #include #endif /* NT */ #include #ifdef HAVE_STRING_H #include #endif /* HAVE_STRING_H */ #ifdef HAVE_STRINGS_H #include #endif /* HAVE_STRINGS_H */ /* Obtained from GNU autoconf manual */ /* AIX requires this to be the first thing in the file. */ #ifdef __GNUC__ # ifndef alloca # define alloca __builtin_alloca # endif #else # if HAVE_ALLOCA_H # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca (); # endif # endif # endif #endif #ifndef NT #include #else #include #endif /* NT */ #ifdef HAVE_RESOLV_H #include #include #endif /* HAVE_RESOLV_H */ #include #include #include typedef void (*void_fn_t)(); typedef int (*int_fn_t)(); typedef void *(*thread_fn_t)(void *); #include #include #include #include #include #include #include #ifdef notdef extern int IPV4; #ifdef HAVE_IPV6 extern int IPV6; #endif /* IPV6 */ #endif #define AFI_IP 1 #define AFI_IP6 2 #define AFI_MAX 3 #define SAFI_UNICAST 1 #define SAFI_MULTICAST 2 #define SAFI_MAX 3 int afi2family (int afi); int family2afi (int family); char *afi2string (int afi); char *safi2string (int safi); #ifndef ON #define ON 1 #endif /* ON */ #ifndef OFF #define OFF 0 #endif /* OFF */ #define NIL (-1) #ifndef INET_ADDRSTRLEN #define INET_ADDRSTRLEN 16 #endif /* INET_ADDRSTRLEN */ #ifdef NT #ifdef HAVE_IPV6 #include #include #endif /* HAVE_IPV6 */ #endif /* NT */ #ifndef HAVE_IPV6 #ifndef AF_INET6 #define AF_INET6 24 /* XXX - may conflict with other value */ #endif #ifndef HAVE_STRUCT_IN6_ADDR struct in6_addr { u_char s6_addr[16]; }; #endif /* HAVE_STRUCT_IN6_ADDR */ #endif /* HAVE_IPV6 */ #include typedef struct _prefix_t { u_short family; /* AF_INET | AF_INET6 */ u_short bitlen; /* same as mask? */ int ref_count; /* reference count */ pthread_mutex_t mutex_lock; /* lock down structure */ union { struct in_addr sin; #ifdef HAVE_IPV6 struct in6_addr sin6; #endif /* IPV6 */ } add; } prefix_t; typedef struct _address_t { u_short family; /* AF_INET | AF_INET6 */ u_short port; /* port number in host byte order */ int ref_count; /* reference count */ pthread_mutex_t mutex_lock; /* lock down structure */ union { struct in_addr sin; #ifdef HAVE_IPV6 struct in6_addr sin6; #endif /* IPV6 */ } add; } address_t; typedef struct _prefix4_t { u_short family; /* AF_INET | AF_INET6 */ u_short bitlen; /* same as mask? */ int ref_count; /* reference count */ pthread_mutex_t mutex_lock; /* lock down structure */ struct in_addr sin; } prefix4_t; #ifdef HAVE_IPV6 typedef struct _prefix6_t { u_short family; /* AF_INET | AF_INET6 */ u_short bitlen; /* same as mask? */ int ref_count; /* reference count */ pthread_mutex_t mutex_lock; /* lock down structure */ struct in6_addr sin6; } prefix6_t; #endif /* IPV6 */ typedef struct _prefix_pair_t { prefix_t *prefix1; prefix_t *prefix2; } prefix_pair_t; #include typedef struct _Route { prefix_t *prefix; void *attr; /* attribure strcutre like bgp_attr_t */ } Route; enum ROUTE_ATTR_TYPES { ROUTE_ATTR_BGP4, ROUTE_ATTR_RIP, ROUTE_ATTR_IDRP }; #ifdef NT #undef interface #endif /* NT */ typedef struct _gateway_t { prefix_t *prefix; struct _interface_t *interface; /* the following two are protocol (BGP) dependent ? */ int AS; u_long routerid; /* the following two are for shared nexthop structure */ int ref_count; /* reference count */ pthread_mutex_t mutex_lock; /* lock down structure */ u_long flags; } gateway_t; #define GATEWAY_LOCAL 0x01 #define GATEWAY_DIRECT 0x02 #define GATEWAY_INDIRECT 0x04 #define GATEWAY_UNSPEC 0x08 #define GATEWAY_LLOCAL 0x10 /* they share the same hash table */ typedef gateway_t nexthop_t; /* this should match with other attributes */ typedef struct _generic_attr_t { u_char type; /* RIP, BGP, OSPF */ int ref_count; pthread_mutex_t mutex_lock; /* lock down structure */ /* here is 3 bytes space */ nexthop_t *nexthop; gateway_t *gateway; /* gateway we learned route from */ u_long tag; nexthop_t *parent; /* parent nexthop in case of IBGP or MULTIHOP */ } generic_attr_t; typedef struct _tuple_t { int len; u_char *data; } tuple_t; extern int VERBOSE_ERROR_FLAG; /* yuck, delete this */ #include typedef struct _mrt_hash_table_t { HASH_TABLE *table; pthread_mutex_t mutex_lock; } mrt_hash_table_t; #ifdef notdef typedef struct _nexthop_t { prefix_t *prefix; int ref_count; /* reference count */ pthread_mutex_t mutex_lock; /* lock down structure */ } nexthop_t; #endif #ifdef HAVE_NET_IF_DL_H #include #endif /* HAVE_NET_IF_DL_H */ #if defined(HAVE_MROUTING) || defined(HAVE_MROUTING6) #include #endif /* HAVE_MROUTING || HAVE_MROUTING6 */ typedef union _sockunion_t { struct sockaddr sa; struct sockaddr_in sin; #ifdef AF_LINK struct sockaddr_dl sdl; #endif /* AF_LINK */ #ifdef HAVE_IPV6 struct sockaddr_in6 sin6; #ifdef RTA_DOWNSTREAM struct sockaddr_inds inds; #endif /* RTA_DOWNSTREAM */ #endif /* HAVE_IPV6 */ } sockunion_t; u_char *sockunion2char (sockunion_t *u); typedef void (*proto_update_route_t) (prefix_t *prefix, generic_attr_t *new_attr, generic_attr_t *old_attr, int pref, int viewno); typedef void (*kernel_update_route_t) (prefix_t *prefix, generic_attr_t *new_attr, generic_attr_t *old_attr, int pref); typedef void (*rib_update_route_t) (prefix_t *prefix, generic_attr_t *new_attr, generic_attr_t *old_attr, int pref, u_long flags, int safi); typedef void (*rib_flush_route_t) (int proto, int afi, int safi); typedef nexthop_t *(*rib_find_best_route_t) (prefix_t *prefix, int safi); typedef nexthop_t *(*rib_find_upstream_t) (prefix_t *prefix, int safi); typedef void (*rib_update_nexthop_t) (int afi, int safi); typedef time_t (*rib_time_t) (int afi, int safi); typedef int (*rib_redistribute_request_t) (int from, int viewno, int to, int on, int afi, int safi); typedef int (*rib_redistribute_network_t) (int from, int viewno, prefix_t *network, int on, int safi); /* Main MRT structure * holds bookkeeping information on gateways, threads, signals, etc * ALL MRT programs depend on this structure */ typedef struct _mrt_t { pthread_mutex_t mutex_lock; /* lock down structure */ trace_t *trace; /* default trace - go away future? */ LINKED_LIST *ll_threads; /* list of all thread_t */ LINKED_LIST *ll_signal_call_fn; /* list of mrt_signal_t */ LINKED_LIST *ll_gateways; /* list of gateway_t for Solaris */ LINKED_LIST *ll_trace; /* list of trace_t */ char *config_file_name; long start_time; /* uptime of system (debugging) */ #ifndef HAVE_LIBPTHREAD /* for use on non-thread systems -- current thread # */ int threadn; #endif /* HAVE_LIBPTHREAD */ u_long protocols; /* protocols enabled */ /* u_long redist[PROTO_MAX + 1]; */ /* protocols redistribute */ proto_update_route_t proto_update_route[PROTO_MAX + 1]; kernel_update_route_t kernel_update_route; rib_update_route_t rib_update_route; rib_flush_route_t rib_flush_route; rib_find_best_route_t rib_find_best_route; rib_find_upstream_t rib_find_upstream; rib_time_t rib_time; rib_update_nexthop_t rib_update_nexthop; rib_redistribute_request_t rib_redistribute_request; rib_redistribute_network_t rib_redistribute_network; /* for rebooting - save cwd, and arguments */ char *cwd; char **argv; int argc; int daemon_mode; mrt_hash_table_t hash_table; #ifdef HAVE_IPV6 mrt_hash_table_t hash_table6; #endif /* HAVE_IPV6 */ volatile int force_exit_flag; #ifndef HAVE_LIBPTHREAD int initialization; #endif /* HAVE_LIBPTHREAD */ int kernel_install_flag4; int kernel_install_flag6; u_long default_id; /* router id for bgp */ int pid; char *version; char *date; } mrt_t; /* must not the same as any signal number */ #define MRT_FORCE_EXIT 999 #define MRT_FORCE_REBOOT 998 #define MRT_FORCE_ABORT 997 typedef struct _redistribute_t { int type; proto_update_route_t fn; } redistribute_t; typedef struct _ll_value_t { int value; LL_POINTERS ptrs; } ll_value_t; extern mrt_t *MRT; extern int IPV4; extern int IPV6; /* Main thread gets all signals. Threads can request to have call_fn * executed upon receipt of a signal */ typedef struct _mrt_signal_t { int signal; void_fn_t call_fn; /* mrt_call_fn_t call_fn; */ } mrt_signal_t; typedef struct _mrt_thread_t { char *name; pthread_t thread; pthread_attr_t attr; schedule_t *schedule; /* schedule sttached to the thread */ } mrt_thread_t; #ifdef HAVE_LIBPTHREAD #define THREAD_SPECIFIC_DATA(type, data, size) \ do { \ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; \ static pthread_key_t key;\ static int need_get_key = 1; \ \ if (need_get_key) { \ pthread_mutex_lock (&mutex); \ /* need double check since this thread may be locked */ \ if (need_get_key) { \ if (pthread_key_create (&key, free) < 0) { \ pthread_mutex_unlock (&mutex); \ data = (type *) NULL; \ perror ("pthread_key_create"); \ abort (); \ break; \ } \ need_get_key = 0; \ } \ pthread_mutex_unlock (&mutex); \ } \ if ((data = (type *) pthread_getspecific (key)) == NULL) { \ if ((data = (type *) calloc (size, sizeof (type))) == NULL) { \ perror ("pthread_getspecific"); \ abort (); \ break; \ } \ if (pthread_setspecific (key, data) < 0) { \ perror ("pthread_setspecific"); \ abort (); \ break; \ } \ } \ } while (0) #else #define THREAD_SPECIFIC_DATA(type, data, size) \ do { \ static type buff[size]; \ data = buff; \ } while (0) #endif /* HAVE_LIBPTHREAD */ #define THREAD_SPECIFIC_STORAGE_LEN 1024 #define THREAD_SPECIFIC_STORAGE_NUM 16 #define THREAD_SPECIFIC_STORAGE2(data, len, num) \ do { \ struct buffer { \ u_char buffs[num][len]; \ u_int i; \ } *buffp; \ \ THREAD_SPECIFIC_DATA (struct buffer, buffp, 1); \ if (buffp) { \ data = (void*)buffp->buffs[buffp->i++%num]; \ } \ else { \ data = (void*)NULL; \ } \ } while (0) #define THREAD_SPECIFIC_STORAGE_LEN 1024 #define THREAD_SPECIFIC_STORAGE_NUM 16 #define THREAD_SPECIFIC_STORAGE(data) THREAD_SPECIFIC_STORAGE2 (\ data, THREAD_SPECIFIC_STORAGE_LEN, THREAD_SPECIFIC_STORAGE_NUM) #define ASSERT(x) { if (!(x)) \ err_dump ("\nAssert failed line %d in %s", __LINE__, __FILE__); } #define UTIL_GET_BYTE(val, cp) ((val) = *(cp)++) #define UTIL_GET_SHORT(val, cp) \ { \ register u_char *val_p; \ val_p = (u_char *) &(val); \ *val_p++ = *(cp)++; \ *val_p++ = *(cp)++; \ } #define UTIL_GET_NETSHORT(val, cp) \ { \ register u_char *val_p; \ val_p = (u_char *) &(val); \ *val_p++ = *(cp)++; \ *val_p++ = *(cp)++; \ (val) = ntohs(val); \ } #define UTIL_GET_LONG(val, cp) \ { \ register u_char *val_p; \ val_p = (u_char *) &(val); \ *val_p++ = *(cp)++; \ *val_p++ = *(cp)++; \ *val_p++ = *(cp)++; \ *val_p++ = *(cp)++; \ } /* This version of UTIL_GET_NETLONG uses ntohl for cross-platform * compatibility, which is A Good Thing (tm) */ #define UTIL_GET_NETLONG(val, cp) \ { \ register u_char *val_p; \ val_p = (u_char *) &(val); \ *val_p++ = *(cp)++; \ *val_p++ = *(cp)++; \ *val_p++ = *(cp)++; \ *val_p++ = *(cp)++; \ (val) = ntohl(val); \ } #define UTIL_GET_BITCOUNT(bitcount, cp) ((bitcount) = *(cp)++) #define UTIL_PUT_BYTE(val, cp) (*(cp)++ = (byte)(val)) #define UTIL_PUT_SHORT(val, cp) \ { \ u_short tmp = (val); \ register u_char *tmp_p = (u_char *) &tmp; \ *(cp)++ = *tmp_p++; \ *(cp)++ = *tmp_p++; \ } /* Network version of UTIL_PUT_SHORT, using htons for cross-platform * compatibility */ #define UTIL_PUT_NETSHORT(val, cp) \ { \ u_short tmp; \ register u_char *val_p; \ tmp = htons(val); \ val_p = (u_char *) &tmp; \ *(cp)++ = *val_p++; \ *(cp)++ = *val_p++; \ } #define UTIL_PUT_LONG(val, cp) \ { \ u_long tmp = (val); \ register u_char *tmp_p = (u_char *) &tmp; \ *(cp)++ = *tmp_p++; \ *(cp)++ = *tmp_p++; \ *(cp)++ = *tmp_p++; \ *(cp)++ = *tmp_p++; \ } /* Network version of UTIL_PUT_LONG which uses htonl to maintain * cross-platform byte-orderings across the network */ #define UTIL_PUT_NETLONG(val, cp) \ { \ u_long tmp; \ register u_char *val_p; \ tmp = htonl(val); \ val_p = (u_char *) &tmp; \ *(cp)++ = *val_p++; \ *(cp)++ = *val_p++; \ *(cp)++ = *val_p++; \ *(cp)++ = *val_p++; \ } #include #include /* public functions */ prefix_t *New_Prefix (int family, void * dest, int bitlen); prefix_t *New_Prefix2 (int family, void * dest, int bitlen, prefix_t *prefix); prefix_t *Change_Prefix (int family, void * dest, int bitlen, prefix_t * prefix); prefix_t *Ref_Prefix (prefix_t * prefix); void Deref_Prefix (prefix_t * prefix); void Delete_Prefix (prefix_t * prefix); int prefix_check_prefix_in_list (LINKED_LIST * ll_prefix, prefix_t * prefix); void print_prefix_list (LINKED_LIST * ll_prefixes); void print_prefix_list_buffer (LINKED_LIST * ll_prefixes, buffer_t * buffer); void print_prefix (prefix_t * p_prefix); void print_pref_prefix_list_buffer (LINKED_LIST * ll_prefixes, u_short *pref, buffer_t * buffer); prefix_t *copy_prefix (prefix_t * prefix); void print_pref_prefix_list (LINKED_LIST * ll_prefixes, u_short *pref); struct sockaddr *prefix_tosockaddr(prefix_t *); prefix_t *sockaddr_toprefix (struct sockaddr *sa); prefix_t *name_toprefix(char *, trace_t *); prefix_t *string_toprefix(char *, trace_t *); char *prefix_toname(prefix_t *prefix); #define prefix_tolong(prefix) (assert ((prefix)->family == AF_INET),\ (prefix)->add.sin.s_addr) #define prefix_tochar(prefix) ((char *)&(prefix)->add.sin) #define prefix_touchar(prefix) ((u_char *)&(prefix)->add.sin) #define prefix_toaddr(prefix) (&(prefix)->add.sin) #define prefix_getfamily(prefix) ((prefix)->family) #define prefix_getlen(prefix) (((prefix)->bitlen)/8) #ifdef HAVE_IPV6 #define prefix_toaddr6(prefix) (assert ((prefix)->family == AF_INET6),\ &(prefix)->add.sin6) #endif /* IPV6 */ #ifdef notdef u_char *prefix_tochar (prefix_t * prefix); #endif int prefix_compare (prefix_t * p1, prefix_t * p2); int prefix_equal (prefix_t * p1, prefix_t * p2); int prefix_compare2 (prefix_t * p1, prefix_t * p2); int prefix_compare_wolen (prefix_t *p, prefix_t *q); int address_equal (prefix_t *p, prefix_t *q); int prefix_compare_wlen (prefix_t *p, prefix_t *q); int a_include_b (prefix_t * a, prefix_t * b); char *prefix_toa (prefix_t * prefix); char *prefix_toa2 (prefix_t * prefix, char *tmp); char *prefix_toax (prefix_t * prefix); char *prefix_toa2x (prefix_t * prefix, char *tmp, int with_len); prefix_t *ascii2prefix (int family, char *string); int my_inet_pton (int af, const char *src, void *dst); /*int my_inet_pton6(int family, const char *string, struct in6_addr *sin6);*/ char *get_netname (int dest, int bitlen); int munge_route_string (); int _atoi (); char *my_strftime (long t, char *fmt); gateway_t *add_bgp_gateway (prefix_t * prefix, int as, u_long id, /* resolve cross reference ... */ struct _interface_t *interface); gateway_t *add_gateway (prefix_t * prefix, int as, /* resolve cross reference ... */ struct _interface_t *interface); /* gateway_t *find_gateway (prefix_t * prefix, int AS); */ char *gateway_toa (char *tmp, gateway_t * gateway); char *gateway_toa2 (gateway_t * gateway); /* void destroy_gateway (gateway_t * gateway); */ nexthop_t * add_bgp_nexthop (prefix_t *prefix, int as, u_long id, struct _interface_t *interface); nexthop_t * add_nexthop (prefix_t *prefix, struct _interface_t *interface); void deref_nexthop (nexthop_t *nexthop); nexthop_t *eval_nexthop (nexthop_t *nexthop); nexthop_t * ref_nexthop (nexthop_t *nexthop); gateway_t * find_gateway (prefix_t *prefix); gateway_t * find_bgp_gateway (prefix_t *prefix, int as, u_long id); int is_prefix_on (prefix_t *prefix, interface_t *interface); int is_prefix_local_on (prefix_t * prefix, interface_t *interface); int nexthop_available (nexthop_t *nexthop); int init_mrt (trace_t *tr); mrt_thread_t *mrt_thread_create (char *name, schedule_t * schedule, thread_fn_t callfn, void *arg); mrt_thread_t *mrt_thread_create2 (char *name, schedule_t * schedule, thread_fn_t callfn, void *arg); int is_ipv4_prefix (char *string); #ifdef HAVE_IPV6 int is_ipv6_prefix (char *string); int ipv6_multicast_addr (struct in6_addr *sin6); int ipv6_link_local_addr (struct in6_addr *sin6); int ipv6_ipv4_addr (struct in6_addr *sin6); int ipv6_compat_addr (struct in6_addr *sin6); int ipv6_any_addr (struct in6_addr *sin6); #endif /* HAVE_IPV6 */ u_char *netmasking (int family, void *addr, u_int bitlen); int comp_with_mask (void *addr, void *dest, u_int mask); int byte_compare (void *addr, void *dest, int bits, void *wildcard); #ifndef NT #include #endif /* NT */ #ifndef HAVE_INET_NTOP const char *inet_ntop (int af, const void *src, char *dst, size_t size); int inet_pton (int af, const char *src, void *dst); #endif /* HAVE_INET_NTOP */ #ifndef HAVE_MEMMOVE #ifdef NT void *memmove (void *dest, const void *src, size_t n); #else char *memmove (char *dest, const char *src, size_t n); #endif /* NT */ #endif /* HAVE_MEMMOVE */ int atox (char *str); char *r_inet_ntoa (char *buf, int n, u_char *l, int len); char *family2string (int family); int is_any_addr (prefix_t *prefix); int prefix_is_unspecified (prefix_t *prefix); int prefix_is_loopback (prefix_t *prefix); int prefix_is_multicast (prefix_t *prefix); int prefix_is_v4compat (prefix_t *prefix); int prefix_is_linklocal (prefix_t *prefix); int prefix_is_v4mapped (prefix_t *prefix); int prefix_is_sitelocal (prefix_t *prefix); int prefix_is_global (prefix_t *prefix); int nonblock_connect (trace_t *default_trace, prefix_t *prefix, int port, int sockfd); void mrt_reboot (void); int init_mrt_reboot (int argc, char *argv[]); void mrt_main_loop (void); void mrt_busy_loop (volatile int *force_exit_flag, int ok); void mrt_switch_schedule (void); int mrt_update_pid (void); void mrt_thread_exit (void); void mrt_thread_kill_all (void); void init_mrt_thread_signals (void); void mrt_exit (int status); void mrt_process_signal (int sig); void mrt_set_force_exit (int code); buffer_t *New_Buffer (int len); void Delete_Buffer (buffer_t *buffer); int string2proto (char *proto_string); char *proto2string (int proto); #define LL_Add2(ll, a) LL_Add (((ll)? (ll): ((ll) = LL_Create (0))), (a)) #define LL_Add3(ll, a) { void *_b; \ LL_Iterate (ll, _b) { if (_b == (a)) break;} if (!_b) LL_Add2 (ll,a);} extern int BGPSIM_TRANSPARENT; int gen_hash_fn (prefix_t * prefix, int size); int gen_lookup_fn (prefix_t * a, prefix_t * b); const char *origin2string (int origin); const int origin2char (int origin); char *bgptype2string (int type); int string2bgptype (char **str); char *proto2string (int proto); char *time2date (int elapsed, char *date); char *safestrncpy (char *dest, const char *src, size_t n); char *etime2ascii (time_t elapsed, char *date); u_long strtoul10 (char *nptr, char **endptr); int ip_hash_fn (prefix_t * prefix, int size); int ip_lookup_fn (prefix_t * a, prefix_t * b); int ip_pair_hash_fn (prefix_pair_t * prefix, int size); int ip_pair_lookup_fn (prefix_pair_t * a, prefix_pair_t * b); #ifndef HAVE_STRTOK_R #define strtok_r(a,b,c) strtok(a,b) #endif /* HAVE_STRTOK_R */ #define open(a,b,c) mrt_open((a),(b),(c),__FILE__,__LINE__) #define close(a) mrt_close((a),__FILE__,__LINE__) #undef socket #define socket(a,b,c) mrt_socket((a),(b),(c),__FILE__,__LINE__) #define accept(a,b,c) mrt_accept((a),(b),(c),__FILE__,__LINE__) int mrt_open (const char *path, int flags, mode_t mode, char *s, int l); int mrt_close (int d, char *s, int l); int mrt_socket (int domain, int type, int protocol, char *s, int l); int mrt_accept (int d, struct sockaddr *addr, int *addrlen, char *s, int l); int ifzero (void *ptr, int size); int ifneg (void *a, void *c, int size); int ifor (void *a, void *b, void *c, int size); int ifand (void *a, void *b, void *c, int size); int ifxor (void *a, void *b, void *c, int size); #ifdef NT /* I don't know exactly but it would reduce code changes */ #define socket_errno() WSAGetLastError() #define EWOULDBLOCK WSAEWOULDBLOCK #define EINPROGRESS WSAEINPROGRESS #define ECONNREFUSED WSAECONNREFUSED #define ETIMEDOUT WSAETIMEDOUT #define ENETUNREACH WSAENETUNREACH #define EHOSTUNREACH WSAEHOSTUNREACH #define EHOSTDOWN WSAEHOSTDOWN #define EISCONN WSAEISCONN //#define EINVAL WSAEINVAL #else #define socket_errno() errno #endif /* NT */ #endif /* _MRT_H */ .