summaryrefslogtreecommitdiff
path: root/ext/dnet/ip.h
blob: 95b7718fbaa22aec50d79009525046e6588121ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
/*
 * ip.h
 *
 * Internet Protocol (RFC 791).
 *
 * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
 *
 * $Id: ip.h,v 1.23 2003/03/16 17:39:17 dugsong Exp $
 */

#ifndef DNET_IP_H
#define DNET_IP_H

#define IP_ADDR_LEN	4		/* IP address length */
#define IP_ADDR_BITS	32		/* IP address bits */

#define IP_HDR_LEN	20		/* base IP header length */
#define IP_OPT_LEN	2		/* base IP option length */
#define IP_OPT_LEN_MAX	40
#define IP_HDR_LEN_MAX	(IP_HDR_LEN + IP_OPT_LEN_MAX)

#define IP_LEN_MAX	65535
#define IP_LEN_MIN	IP_HDR_LEN

typedef uint32_t	ip_addr_t;

#ifndef __GNUC__
# define __attribute__(x)
# pragma pack(1)
#endif

/*
 * IP header, without options
 */
struct ip_hdr {
#if DNET_BYTESEX == DNET_BIG_ENDIAN
        uint8_t		ip_v:4,		/* version */
                        ip_hl:4;	/* header length (incl any options) */
#elif DNET_BYTESEX == DNET_LIL_ENDIAN
        uint8_t		ip_hl:4,
                        ip_v:4;
#else
# error "need to include <dnet.h>"
#endif
        uint8_t		ip_tos;		/* type of service */
        uint16_t	ip_len;		/* total length (incl header) */
        uint16_t	ip_id;		/* identification */
        uint16_t	ip_off;		/* fragment offset and flags */
        uint8_t		ip_ttl;		/* time to live */
        uint8_t		ip_p;		/* protocol */
        uint16_t	ip_sum;		/* checksum */
        ip_addr_t	ip_src;		/* source address */
        ip_addr_t	ip_dst;		/* destination address */
};

/*
 * Type of service (ip_tos), RFC 1349 ("obsoleted by RFC 2474")
 */
#define IP_TOS_DEFAULT		0x00	/* default */
#define IP_TOS_LOWDELAY		0x10	/* low delay */
#define IP_TOS_THROUGHPUT	0x08	/* high throughput */
#define IP_TOS_RELIABILITY	0x04	/* high reliability */
#define IP_TOS_LOWCOST		0x02	/* low monetary cost - XXX */
#define IP_TOS_ECT		0x02	/* ECN-capable transport */
#define IP_TOS_CE		0x01	/* congestion experienced */

/*
 * IP precedence (high 3 bits of ip_tos), hopefully unused
 */
#define IP_TOS_PREC_ROUTINE		0x00
#define IP_TOS_PREC_PRIORITY		0x20
#define IP_TOS_PREC_IMMEDIATE		0x40
#define IP_TOS_PREC_FLASH		0x60
#define IP_TOS_PREC_FLASHOVERRIDE	0x80
#define IP_TOS_PREC_CRITIC_ECP		0xa0
#define IP_TOS_PREC_INTERNETCONTROL	0xc0
#define IP_TOS_PREC_NETCONTROL		0xe0

/*
 * Fragmentation flags (ip_off)
 */
#define IP_RF		0x8000		/* reserved */
#define IP_DF		0x4000		/* don't fragment */
#define IP_MF		0x2000		/* more fragments (not last frag) */
#define IP_OFFMASK	0x1fff		/* mask for fragment offset */

/*
 * Time-to-live (ip_ttl), seconds
 */
#define IP_TTL_DEFAULT	64		/* default ttl, RFC 1122, RFC 1340 */
#define IP_TTL_MAX	255		/* maximum ttl */

/*
 * Protocol (ip_p) - http://www.iana.org/assignments/protocol-numbers
 */
#define	IP_PROTO_IP		0		/* dummy for IP */
#define IP_PROTO_HOPOPTS	IP_PROTO_IP	/* IPv6 hop-by-hop options */
#define	IP_PROTO_ICMP		1		/* ICMP */
#define	IP_PROTO_IGMP		2		/* IGMP */
#define IP_PROTO_GGP		3		/* gateway-gateway protocol */
#define	IP_PROTO_IPIP		4		/* IP in IP */
#define IP_PROTO_ST		5		/* ST datagram mode */
#define	IP_PROTO_TCP		6		/* TCP */
#define IP_PROTO_CBT		7		/* CBT */
#define	IP_PROTO_EGP		8		/* exterior gateway protocol */
#define IP_PROTO_IGP		9		/* interior gateway protocol */
#define IP_PROTO_BBNRCC		10		/* BBN RCC monitoring */
#define IP_PROTO_NVP		11		/* Network Voice Protocol */
#define	IP_PROTO_PUP		12		/* PARC universal packet */
#define IP_PROTO_ARGUS		13		/* ARGUS */
#define IP_PROTO_EMCON		14		/* EMCON */
#define IP_PROTO_XNET		15		/* Cross Net Debugger */
#define IP_PROTO_CHAOS		16		/* Chaos */
#define	IP_PROTO_UDP		17		/* UDP */
#define IP_PROTO_MUX		18		/* multiplexing */
#define IP_PROTO_DCNMEAS	19		/* DCN measurement */
#define IP_PROTO_HMP		20		/* Host Monitoring Protocol */
#define IP_PROTO_PRM		21		/* Packet Radio Measurement */
#define	IP_PROTO_IDP		22		/* Xerox NS IDP */
#define IP_PROTO_TRUNK1		23		/* Trunk-1 */
#define IP_PROTO_TRUNK2		24		/* Trunk-2 */
#define IP_PROTO_LEAF1		25		/* Leaf-1 */
#define IP_PROTO_LEAF2		26		/* Leaf-2 */
#define IP_PROTO_RDP		27		/* "Reliable Datagram" proto */
#define IP_PROTO_IRTP		28		/* Inet Reliable Transaction */
#define	IP_PROTO_TP		29 		/* ISO TP class 4 */
#define IP_PROTO_NETBLT		30		/* Bulk Data Transfer */
#define IP_PROTO_MFPNSP		31		/* MFE Network Services */
#define IP_PROTO_MERITINP	32		/* Merit Internodal Protocol */
#define IP_PROTO_SEP		33		/* Sequential Exchange proto */
#define IP_PROTO_3PC		34		/* Third Party Connect proto */
#define IP_PROTO_IDPR		35		/* Interdomain Policy Route */
#define IP_PROTO_XTP		36		/* Xpress Transfer Protocol */
#define IP_PROTO_DDP		37		/* Datagram Delivery Proto */
#define IP_PROTO_CMTP		38		/* IDPR Ctrl Message Trans */
#define IP_PROTO_TPPP		39		/* TP++ Transport Protocol */
#define IP_PROTO_IL		40		/* IL Transport Protocol */
#define IP_PROTO_IPV6		41		/* IPv6 */
#define IP_PROTO_SDRP		42		/* Source Demand Routing */
#define IP_PROTO_ROUTING	43		/* IPv6 routing header */
#define IP_PROTO_FRAGMENT	44		/* IPv6 fragmentation header */
#define IP_PROTO_RSVP		46		/* Reservation protocol */
#define	IP_PROTO_GRE		47		/* General Routing Encap */
#define IP_PROTO_MHRP		48		/* Mobile Host Routing */
#define IP_PROTO_ENA		49		/* ENA */
#define	IP_PROTO_ESP		50		/* Encap Security Payload */
#define	IP_PROTO_AH		51		/* Authentication Header */
#define IP_PROTO_INLSP		52		/* Integated Net Layer Sec */
#define IP_PROTO_SWIPE		53		/* SWIPE */
#define IP_PROTO_NARP		54		/* NBMA Address Resolution */
#define	IP_PROTO_MOBILE		55		/* Mobile IP, RFC 2004 */
#define IP_PROTO_TLSP		56		/* Transport Layer Security */
#define IP_PROTO_SKIP		57		/* SKIP */
#define IP_PROTO_ICMPV6		58		/* ICMP for IPv6 */
#define IP_PROTO_NONE		59		/* IPv6 no next header */
#define IP_PROTO_DSTOPTS	60		/* IPv6 destination options */
#define IP_PROTO_ANYHOST	61		/* any host internal proto */
#define IP_PROTO_CFTP		62		/* CFTP */
#define IP_PROTO_ANYNET		63		/* any local network */
#define IP_PROTO_EXPAK		64		/* SATNET and Backroom EXPAK */
#define IP_PROTO_KRYPTOLAN	65		/* Kryptolan */
#define IP_PROTO_RVD		66		/* MIT Remote Virtual Disk */
#define IP_PROTO_IPPC		67		/* Inet Pluribus Packet Core */
#define IP_PROTO_DISTFS		68		/* any distributed fs */
#define IP_PROTO_SATMON		69		/* SATNET Monitoring */
#define IP_PROTO_VISA		70		/* VISA Protocol */
#define IP_PROTO_IPCV		71		/* Inet Packet Core Utility */
#define IP_PROTO_CPNX		72		/* Comp Proto Net Executive */
#define IP_PROTO_CPHB		73		/* Comp Protocol Heart Beat */
#define IP_PROTO_WSN		74		/* Wang Span Network */
#define IP_PROTO_PVP		75		/* Packet Video Protocol */
#define IP_PROTO_BRSATMON	76		/* Backroom SATNET Monitor */
#define IP_PROTO_SUNND		77		/* SUN ND Protocol */
#define IP_PROTO_WBMON		78		/* WIDEBAND Monitoring */
#define IP_PROTO_WBEXPAK	79		/* WIDEBAND EXPAK */
#define	IP_PROTO_EON		80		/* ISO CNLP */
#define IP_PROTO_VMTP		81		/* Versatile Msg Transport*/
#define IP_PROTO_SVMTP		82		/* Secure VMTP */
#define IP_PROTO_VINES		83		/* VINES */
#define IP_PROTO_TTP		84		/* TTP */
#define IP_PROTO_NSFIGP		85		/* NSFNET-IGP */
#define IP_PROTO_DGP		86		/* Dissimilar Gateway Proto */
#define IP_PROTO_TCF		87		/* TCF */
#define IP_PROTO_EIGRP		88		/* EIGRP */
#define IP_PROTO_OSPF		89		/* Open Shortest Path First */
#define IP_PROTO_SPRITERPC	90		/* Sprite RPC Protocol */
#define IP_PROTO_LARP		91		/* Locus Address Resolution */
#define IP_PROTO_MTP		92		/* Multicast Transport Proto */
#define IP_PROTO_AX25		93		/* AX.25 Frames */
#define IP_PROTO_IPIPENCAP	94		/* yet-another IP encap */
#define IP_PROTO_MICP		95		/* Mobile Internet Ctrl */
#define IP_PROTO_SCCSP		96		/* Semaphore Comm Sec Proto */
#define IP_PROTO_ETHERIP	97		/* Ethernet in IPv4 */
#define	IP_PROTO_ENCAP		98		/* encapsulation header */
#define IP_PROTO_ANYENC		99		/* private encryption scheme */
#define IP_PROTO_GMTP		100		/* GMTP */
#define IP_PROTO_IFMP		101		/* Ipsilon Flow Mgmt Proto */
#define IP_PROTO_PNNI		102		/* PNNI over IP */
#define IP_PROTO_PIM		103		/* Protocol Indep Multicast */
#define IP_PROTO_ARIS		104		/* ARIS */
#define IP_PROTO_SCPS		105		/* SCPS */
#define IP_PROTO_QNX		106		/* QNX */
#define IP_PROTO_AN		107		/* Active Networks */
#define IP_PROTO_IPCOMP		108		/* IP Payload Compression */
#define IP_PROTO_SNP		109		/* Sitara Networks Protocol */
#define IP_PROTO_COMPAQPEER	110		/* Compaq Peer Protocol */
#define IP_PROTO_IPXIP		111		/* IPX in IP */
#define IP_PROTO_VRRP		112		/* Virtual Router Redundancy */
#define IP_PROTO_PGM		113		/* PGM Reliable Transport */
#define IP_PROTO_ANY0HOP	114		/* 0-hop protocol */
#define IP_PROTO_L2TP		115		/* Layer 2 Tunneling Proto */
#define IP_PROTO_DDX		116		/* D-II Data Exchange (DDX) */
#define IP_PROTO_IATP		117		/* Interactive Agent Xfer */
#define IP_PROTO_STP		118		/* Schedule Transfer Proto */
#define IP_PROTO_SRP		119		/* SpectraLink Radio Proto */
#define IP_PROTO_UTI		120		/* UTI */
#define IP_PROTO_SMP		121		/* Simple Message Protocol */
#define IP_PROTO_SM		122		/* SM */
#define IP_PROTO_PTP		123		/* Performance Transparency */
#define IP_PROTO_ISIS		124		/* ISIS over IPv4 */
#define IP_PROTO_FIRE		125		/* FIRE */
#define IP_PROTO_CRTP		126		/* Combat Radio Transport */
#define IP_PROTO_CRUDP		127		/* Combat Radio UDP */
#define IP_PROTO_SSCOPMCE	128		/* SSCOPMCE */
#define IP_PROTO_IPLT		129		/* IPLT */
#define IP_PROTO_SPS		130		/* Secure Packet Shield */
#define IP_PROTO_PIPE		131		/* Private IP Encap in IP */
#define IP_PROTO_SCTP		132		/* Stream Ctrl Transmission */
#define IP_PROTO_FC		133		/* Fibre Channel */
#define IP_PROTO_RSVPIGN	134		/* RSVP-E2E-IGNORE */
#define	IP_PROTO_RAW		255		/* Raw IP packets */
#define IP_PROTO_RESERVED	IP_PROTO_RAW	/* Reserved */
#define	IP_PROTO_MAX		255

/*
 * Option types (opt_type) - http://www.iana.org/assignments/ip-parameters
 */
#define IP_OPT_CONTROL		0x00		/* control */
#define IP_OPT_DEBMEAS		0x40		/* debugging & measurement */
#define IP_OPT_COPY		0x80		/* copy into all fragments */
#define IP_OPT_RESERVED1	0x20
#define IP_OPT_RESERVED2	0x60

#define IP_OPT_EOL	  0			/* end of option list */
#define IP_OPT_NOP	  1			/* no operation */
#define IP_OPT_SEC	 (2|IP_OPT_COPY)	/* DoD basic security */
#define IP_OPT_LSRR	 (3|IP_OPT_COPY)	/* loose source route */
#define IP_OPT_TS	 (4|IP_OPT_DEBMEAS)	/* timestamp */
#define IP_OPT_ESEC	 (5|IP_OPT_COPY)	/* DoD extended security */
#define IP_OPT_CIPSO	 (6|IP_OPT_COPY)	/* commercial security */
#define IP_OPT_RR	  7			/* record route */
#define IP_OPT_SATID	 (8|IP_OPT_COPY)	/* stream ID (obsolete) */
#define IP_OPT_SSRR	 (9|IP_OPT_COPY)	/* strict source route */
#define IP_OPT_ZSU	 10			/* experimental measurement */
#define IP_OPT_MTUP	 11			/* MTU probe */
#define IP_OPT_MTUR	 12			/* MTU reply */
#define IP_OPT_FINN	(13|IP_OPT_COPY|IP_OPT_DEBMEAS)	/* exp flow control */
#define IP_OPT_VISA	(14|IP_OPT_COPY)	/* exp access control */
#define IP_OPT_ENCODE	 15			/* ??? */
#define IP_OPT_IMITD	(16|IP_OPT_COPY)	/* IMI traffic descriptor */
#define IP_OPT_EIP	(17|IP_OPT_COPY)	/* extended IP, RFC 1385 */
#define IP_OPT_TR	(18|IP_OPT_DEBMEAS)	/* traceroute */
#define IP_OPT_ADDEXT	(19|IP_OPT_COPY)	/* IPv7 ext addr, RFC 1475 */
#define IP_OPT_RTRALT	(20|IP_OPT_COPY)	/* router alert, RFC 2113 */
#define IP_OPT_SDB	(21|IP_OPT_COPY)	/* directed bcast, RFC 1770 */
#define IP_OPT_NSAPA	(22|IP_OPT_COPY)	/* NSAP addresses */
#define IP_OPT_DPS	(23|IP_OPT_COPY)	/* dynamic packet state */
#define IP_OPT_UMP	(24|IP_OPT_COPY)	/* upstream multicast */
#define IP_OPT_MAX	 25

#define IP_OPT_COPIED(o)	((o) & 0x80)
#define IP_OPT_CLASS(o)		((o) & 0x60)
#define IP_OPT_NUMBER(o)	((o) & 0x1f)
#define IP_OPT_TYPEONLY(o)	((o) == IP_OPT_EOL || (o) == IP_OPT_NOP)

/*
 * Security option data - RFC 791, 3.1
 */
struct ip_opt_data_sec {
        uint16_t	s;		/* security */
        uint16_t	c;		/* compartments */
        uint16_t	h;		/* handling restrictions */
        uint8_t		tcc[3];		/* transmission control code */
} __attribute__((__packed__));

#define IP_OPT_SEC_UNCLASS	0x0000	/* unclassified */
#define IP_OPT_SEC_CONFID	0xf135	/* confidential */
#define IP_OPT_SEC_EFTO		0x789a	/* EFTO */
#define IP_OPT_SEC_MMMM		0xbc4d	/* MMMM */
#define IP_OPT_SEC_PROG		0x5e26	/* PROG */
#define IP_OPT_SEC_RESTR	0xaf13	/* restricted */
#define IP_OPT_SEC_SECRET	0xd788	/* secret */
#define IP_OPT_SEC_TOPSECRET	0x6bc5	/* top secret */

/*
 * {Loose Source, Record, Strict Source} Route option data - RFC 791, 3.1
 */
struct ip_opt_data_rr {
        uint8_t		ptr;		/* from start of option, >= 4 */
        uint32_t	iplist __flexarr; /* list of IP addresses */
} __attribute__((__packed__));

/*
 * Timestamp option data - RFC 791, 3.1
 */
struct ip_opt_data_ts {
        uint8_t		ptr;		/* from start of option, >= 5 */
#if DNET_BYTESEX == DNET_BIG_ENDIAN
        uint8_t		oflw:4,		/* number of IPs skipped */
                        flg:4;		/* address[ / timestamp] flag */
#elif DNET_BYTESEX == DNET_LIL_ENDIAN
        uint8_t		flg:4,
                        oflw:4;
#endif
        uint32_t	ipts __flexarr;	/* IP address [/ timestamp] pairs */
} __attribute__((__packed__));

#define IP_OPT_TS_TSONLY	0	/* timestamps only */
#define IP_OPT_TS_TSADDR	1	/* IP address / timestamp pairs */
#define IP_OPT_TS_PRESPEC	3	/* IP address / zero timestamp pairs */

/*
 * Traceroute option data - RFC 1393, 2.2
 */
struct ip_opt_data_tr {
        uint16_t	id;		/* ID number */
        uint16_t	ohc;		/* outbound hop count */
        uint16_t	rhc;		/* return hop count */
        uint32_t	origip;		/* originator IP address */
} __attribute__((__packed__));

/*
 * IP option (following IP header)
 */
struct ip_opt {
        uint8_t		opt_type;	/* option type */
        uint8_t		opt_len;	/* option length >= IP_OPT_LEN */
        union ip_opt_data {
                struct ip_opt_data_sec	sec;	   /* IP_OPT_SEC */
                struct ip_opt_data_rr	rr;	   /* IP_OPT_{L,S}RR */
                struct ip_opt_data_ts	ts;	   /* IP_OPT_TS */
                uint16_t		satid;	   /* IP_OPT_SATID */
                uint16_t		mtu;	   /* IP_OPT_MTU{P,R} */
                struct ip_opt_data_tr	tr;	   /* IP_OPT_TR */
                uint32_t		addext[2]; /* IP_OPT_ADDEXT */
                uint16_t		rtralt;    /* IP_OPT_RTRALT */
                uint32_t		sdb[9];    /* IP_OPT_SDB */
                uint8_t			data8[IP_OPT_LEN_MAX - IP_OPT_LEN];
        } opt_data;
} __attribute__((__packed__));

#ifndef __GNUC__
# pragma pack()
#endif

/*
 * Classful addressing
 */
#define	IP_CLASSA(i)		(((uint32_t)(i) & htonl(0x80000000)) == \
                                 htonl(0x00000000))
#define	IP_CLASSA_NET		(htonl(0xff000000))
#define	IP_CLASSA_NSHIFT	24
#define	IP_CLASSA_HOST		(htonl(0x00ffffff))
#define	IP_CLASSA_MAX		128

#define	IP_CLASSB(i)		(((uint32_t)(i) & htonl(0xc0000000)) == \
                                 htonl(0x80000000))
#define	IP_CLASSB_NET		(htonl(0xffff0000))
#define	IP_CLASSB_NSHIFT	16
#define	IP_CLASSB_HOST		(htonl(0x0000ffff))
#define	IP_CLASSB_MAX		65536

#define	IP_CLASSC(i)		(((uint32_t)(i) & htonl(0xe0000000)) == \
                                 htonl(0xc0000000))
#define	IP_CLASSC_NET		(htonl(0xffffff00))
#define	IP_CLASSC_NSHIFT	8
#define	IP_CLASSC_HOST		(htonl(0x000000ff))

#define	IP_CLASSD(i)		(((uint32_t)(i) & htonl(0xf0000000)) == \
                                 htonl(0xe0000000))
/* These ones aren't really net and host fields, but routing needn't know. */
#define	IP_CLASSD_NET		(htonl(0xf0000000))
#define	IP_CLASSD_NSHIFT	28
#define	IP_CLASSD_HOST		(htonl(0x0fffffff))
#define	IP_MULTICAST(i)		IP_CLASSD(i)

#define	IP_EXPERIMENTAL(i)	(((uint32_t)(i) & htonl(0xf0000000)) == \
                                 htonl(0xf0000000))
#define	IP_BADCLASS(i)		(((uint32_t)(i) & htonl(0xf0000000)) == \
                                 htonl(0xf0000000))
#define	IP_LOCAL_GROUP(i)	(((uint32_t)(i) & htonl(0xffffff00)) == \
                                 htonl(0xe0000000))
/*
 * Reserved addresses
 */
#define IP_ADDR_ANY		(htonl(0x00000000))	/* 0.0.0.0 */
#define IP_ADDR_BROADCAST	(htonl(0xffffffff))	/* 255.255.255.255 */
#define IP_ADDR_LOOPBACK	(htonl(0x7f000001))	/* 127.0.0.1 */
#define IP_ADDR_MCAST_ALL	(htonl(0xe0000001))	/* 224.0.0.1 */
#define IP_ADDR_MCAST_LOCAL	(htonl(0xe00000ff))	/* 224.0.0.225 */

#define ip_pack_hdr(hdr, tos, len, id, off, ttl, p, src, dst) do {	\
        struct ip_hdr *ip_pack_p = (struct ip_hdr *)(hdr);		\
        ip_pack_p->ip_v = 4; ip_pack_p->ip_hl = 5;			\
        ip_pack_p->ip_tos = tos; ip_pack_p->ip_len = htons(len);	\
        ip_pack_p->ip_id = htons(id); ip_pack_p->ip_off = htons(off);	\
        ip_pack_p->ip_ttl = ttl; ip_pack_p->ip_p = p;			\
        ip_pack_p->ip_src = src; ip_pack_p->ip_dst = dst;		\
} while (0)

typedef struct ip_handle ip_t;

__BEGIN_DECLS
ip_t	*ip_open(void);
size_t	 ip_send(ip_t *i, const void *buf, size_t len);
ip_t	*ip_close(ip_t *i);

char	*ip_ntop(const ip_addr_t *ip, char *dst, size_t len);
int	 ip_pton(const char *src, ip_addr_t *dst);
char	*ip_ntoa(const ip_addr_t *ip);
#define	 ip_aton ip_pton

size_t	 ip_add_option(void *buf, size_t len,
            int proto, const void *optbuf, size_t optlen);
void	 ip_checksum(void *buf, size_t len);

inline int
ip_cksum_add(const void *buf, size_t len, int cksum)
{
        uint16_t *sp = (uint16_t *)buf;
        int n, sn;

        sn = len / 2;
        n = (sn + 15) / 16;

        /* XXX - unroll loop using Duff's device. */
        switch (sn % 16) {
        case 0:	do {
                cksum += *sp++;
        case 15:
                cksum += *sp++;
        case 14:
                cksum += *sp++;
        case 13:
                cksum += *sp++;
        case 12:
                cksum += *sp++;
        case 11:
                cksum += *sp++;
        case 10:
                cksum += *sp++;
        case 9:
                cksum += *sp++;
        case 8:
                cksum += *sp++;
        case 7:
                cksum += *sp++;
        case 6:
                cksum += *sp++;
        case 5:
                cksum += *sp++;
        case 4:
                cksum += *sp++;
        case 3:
                cksum += *sp++;
        case 2:
                cksum += *sp++;
        case 1:
                cksum += *sp++;
                } while (--n > 0);
        }
        if (len & 1)
                cksum += htons(*(u_char *)sp << 8);

        return (cksum);
}

inline uint16_t
ip_cksum_carry(int x)
{
        x = (x >> 16) + (x & 0xffff);
        return ~(x + (x >> 16)) & 0xffff;
}

__END_DECLS

#endif /* DNET_IP_H */