/*
 * INET		An implementation of the TCP/IP protocol suite for the LINUX
 *		operating system.  INET is implemented using the  BSD Socket
 *		interface as the means of communication with the user level.
 *
 *		Definitions of the Internet Protocol.
 *
 * Version:	@(#)in.h	1.0.1	04/21/93
 *
 * Authors:	Original taken from the GNU Project <netinet/in.h> file.
 *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
 *
 *		This program is free software; you can redistribute it and/or
 *		modify it under the terms of the GNU General Public License
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 */
#ifndef _LINUX_IN_H
#define _LINUX_IN_H


/* Standard well-defined IP protocols.  */
enum {
  IPPROTO_IP = 0,		/* Dummy protocol for TCP		*/
  IPPROTO_ICMP = 1,		/* Internet Control Message Protocol	*/
  IPPROTO_GGP = 2,		/* Gateway Protocol (deprecated)	*/
  IPPROTO_TCP = 6,		/* Transmission Control Protocol	*/
  IPPROTO_EGP = 8,		/* Exterior Gateway Protocol		*/
  IPPROTO_PUP = 12,		/* PUP protocol				*/
  IPPROTO_UDP = 17,		/* User Datagram Protocol		*/
  IPPROTO_IDP = 22,		/* XNS IDP protocol			*/

  IPPROTO_RAW = 255,		/* Raw IP packets			*/
  IPPROTO_MAX
};


/* Internet address. */
struct in_addr {
	unsigned long int	s_addr;
};


/* Structure describing an Internet (IP) socket address. */
#define __SOCK_SIZE__	16		/* sizeof(struct sockaddr)	*/
struct sockaddr_in {
  short int		sin_family;	/* Address family		*/
  unsigned short int	sin_port;	/* Port number			*/
  struct in_addr	sin_addr;	/* Internet address		*/

  /* Pad to size of `struct sockaddr'. */
  unsigned char		__pad[__SOCK_SIZE__ - sizeof(short int) -
			sizeof(unsigned short int) - sizeof(struct in_addr)];
};
#define sin_zero	__pad		/* for BSD UNIX comp. -FvK	*/


/*
 * Definitions of the bits in an Internet address integer.
 * On subnets, host and network parts are found according
 * to the subnet mask, not these masks.
 */
#define	IN_CLASSA(a)		((((long int) (a)) & 0x80000000) == 0)
#define	IN_CLASSA_NET		0xff000000
#define	IN_CLASSA_NSHIFT	24
#define	IN_CLASSA_HOST		(0xffffffff & ~IN_CLASSA_NET)
#define	IN_CLASSA_MAX		128

#define	IN_CLASSB(a)		((((long int) (a)) & 0xc0000000) == 0x80000000)
#define	IN_CLASSB_NET		0xffff0000
#define	IN_CLASSB_NSHIFT	16
#define	IN_CLASSB_HOST		(0xffffffff & ~IN_CLASSB_NET)
#define	IN_CLASSB_MAX		65536

#define	IN_CLASSC(a)		((((long int) (a)) & 0xc0000000) == 0xc0000000)
#define	IN_CLASSC_NET		0xffffff00
#define	IN_CLASSC_NSHIFT	8
#define	IN_CLASSC_HOST		(0xffffffff & ~IN_CLASSC_NET)

#define	IN_CLASSD(a)		((((long int) (a)) & 0xf0000000) == 0xe0000000)
#define	IN_MULTICAST(a)		IN_CLASSD(a)

#define	IN_EXPERIMENTAL(a)	((((long int) (a)) & 0xe0000000) == 0xe0000000)
#define	IN_BADCLASS(a)		((((long int) (a)) & 0xf0000000) == 0xf0000000)

/* Address to accept any incoming messages. */
#define	INADDR_ANY		((unsigned long int) 0x00000000)

/* Address to send to all hosts. */
#define	INADDR_BROADCAST	((unsigned long int) 0xffffffff)

/* Address indicating an error return. */
#define	INADDR_NONE		0xffffffff

/* Network number for local host loopback. */
#define	IN_LOOPBACKNET		127

/* Address to loopback in software to local host.  */
#define	INADDR_LOOPBACK		0x7f000001	/* 127.0.0.1		*/


/*
 * Options for use with `getsockopt' and `setsockopt' at
 * the IP level.  LINUX does not yet have the IP_OPTIONS
 * option (grin), so we undefine it for now.- HJ && FvK
 */
#if 0
# define IP_OPTIONS	1		/* IP per-packet options	*/
#endif
#define IP_HDRINCL	2		/* raw packet header option	*/


/* Linux Internet number representation function declarations. */
#undef ntohl
#undef ntohs
#undef htonl
#undef htons

extern unsigned long int	ntohl(unsigned long int);
extern unsigned short int	ntohs(unsigned short int);
extern unsigned long int	htonl(unsigned long int);
extern unsigned short int	htons(unsigned short int);

#ifdef __i386__
static __inline__ unsigned long int
__ntohl(unsigned long int x)
{
  register unsigned long int tmp __asm__ ("ax") = x;
  __asm__ __volatile__ ("xchgb %%al,%%ah\n\t"   /* swap lower bytes	*/
		"rorl $16,%%eax\n\t"		/* swap words		*/
		"xchgb %%al,%%ah\n\t"		/* swap higher bytes	*/
		: "=a" (tmp) : "a" (tmp) );
  return(tmp);
}

static __inline__ unsigned short int
__ntohs(unsigned short int x)
{
  register unsigned short int tmp __asm__ ("ax") = x;
  __asm__ __volatile__ ("xchgb %%al,%%ah\n\t"	/* swap bytes		*/
		: "=a" (tmp) : "a" (tmp));
  return(tmp);
}

static __inline__ unsigned long int
__htonl(unsigned long int x)
{
  register unsigned long int tmp __asm__ ("ax") = x;
  __asm__ __volatile__ ("xchgb %%al,%%ah\n\t"	/* swap lower bytes	*/
		"rorl $16,%%eax\n\t"		/* swap words		*/
		"xchgb %%al,%%ah\n\t"		/* swap higher bytes	*/
		: "=a" (tmp) : "a" (tmp));
  return(tmp);
}

static __inline__ unsigned short int
__htons(unsigned short int x)
{
  register unsigned short int tmp __asm__ ("ax") = x;
  __asm__ __volatile__ ("xchgb %%al,%%ah\n\t"   /* swap bytes */
		: "=a" (tmp) : "a" (tmp));
  return(tmp);
}
#else
static __inline__ unsigned long int
__ntohl(unsigned long int x)
{
  return x;
}

static __inline__ unsigned short int
__ntohs(unsigned short int x)
{
  return x;}

static __inline__ unsigned long int
__htonl(unsigned long int x)
{
  return x;
}

static __inline__ unsigned short int
__htons(unsigned short int x)
{
  return x;
}
#endif

#ifdef  __OPTIMIZE__
#  define ntohl(x)	__ntohl((x))
#  define ntohs(x)	__ntohs((x))
#  define htonl(x)	__htonl((x))
#  define htons(x)	__htons((x))
#endif

#endif	/* _LINUX_IN_H */
