1 /**
2  * D header file for POSIX.
3  *
4  * Copyright: Public Domain
5  * License:   Public Domain
6  * Authors:   Sean Kelly
7  * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
8  */
9 module tango.stdc.posix.netinet.in_;
10 
11 private import tango.stdc.posix.config;
12 public import tango.stdc.inttypes : uint32_t, uint16_t, uint8_t;
13 public import tango.stdc.posix.arpa.inet;
14 public import tango.stdc.posix.sys.socket; // for sa_family_t
15 
16 extern (C):
17 
18 //
19 // Required
20 //
21 /*
22 NOTE: The following must must be defined in tango.stdc.posix.arpa.inet to break
23       a circular import: in_port_t, in_addr_t, struct in_addr, INET_ADDRSTRLEN.
24 
25 in_port_t
26 in_addr_t
27 
28 sa_family_t // from tango.stdc.posix.sys.socket
29 uint8_t     // from tango.stdc.inttypes
30 uint32_t    // from tango.stdc.inttypes
31 
32 struct in_addr
33 {
34     in_addr_t   s_addr;
35 }
36 
37 struct sockaddr_in
38 {
39     sa_family_t sin_family;
40     in_port_t   sin_port;
41     in_addr     sin_addr;
42 }
43 
44 IPPROTO_IP
45 IPPROTO_ICMP
46 IPPROTO_TCP
47 IPPROTO_UDP
48 
49 INADDR_ANY
50 INADDR_BROADCAST
51 
52 INET_ADDRSTRLEN
53 
54 htonl() // from tango.stdc.posix.arpa.inet
55 htons() // from tango.stdc.posix.arpa.inet
56 ntohl() // from tango.stdc.posix.arpa.inet
57 ntohs() // from tango.stdc.posix.arpa.inet
58 */
59 
60 version( linux )
61 {
62     private const __SOCK_SIZE__ = 16;
63 
64     struct sockaddr_in
65     {
66         sa_family_t sin_family;
67         in_port_t   sin_port;
68         in_addr     sin_addr;
69 
70         /* Pad to size of `struct sockaddr'. */
71         ubyte[__SOCK_SIZE__ - sa_family_t.sizeof -
72               in_port_t.sizeof - in_addr.sizeof] __pad;
73     }
74 
75     enum
76     {
77         IPPROTO_IP   = 0,
78         IPPROTO_ICMP = 1,
79         IPPROTO_TCP  = 6,
80         IPPROTO_UDP  = 17
81     }
82 
83     const uint INADDR_ANY       = 0x00000000;
84     const uint INADDR_BROADCAST = 0xffffffff;
85 }
86 else version(OSX)
87 {
88     private const __SOCK_SIZE__ = 16;
89 
90     struct sockaddr_in
91     {
92         ubyte       sin_len;
93         sa_family_t sin_family;
94         in_port_t   sin_port;
95         in_addr     sin_addr;
96         ubyte[8]    sin_zero;
97     }
98 
99     enum
100     {
101         IPPROTO_IP   = 0,
102         IPPROTO_ICMP = 1,
103         IPPROTO_TCP  = 6,
104         IPPROTO_UDP  = 17
105     }
106 
107     const uint INADDR_ANY       = 0x00000000;
108     const uint INADDR_BROADCAST = 0xffffffff;
109 }
110 else version( FreeBSD )
111 {
112     private const __SOCK_SIZE__ = 16;
113 
114     struct sockaddr_in
115     {
116         ubyte       sin_len;
117         sa_family_t sin_family;
118         in_port_t   sin_port;
119         in_addr     sin_addr;
120         ubyte[8]    sin_zero;
121     }
122 
123     enum
124     {
125         IPPROTO_IP   = 0,
126         IPPROTO_ICMP = 1,
127         IPPROTO_TCP  = 6,
128         IPPROTO_UDP  = 17
129     }
130 
131     const uint INADDR_ANY       = 0x00000000;
132     const uint INADDR_BROADCAST = 0xffffffff;
133 }
134 else version( solaris )
135 {
136     struct sockaddr_in
137     {
138         sa_family_t sin_family;
139         in_port_t   sin_port;
140         in_addr     sin_addr;
141         ubyte[8]    sin_zero;
142     }
143 
144     enum
145     {
146         IPPROTO_IP   = 0,
147         IPPROTO_ICMP = 1,
148         IPPROTO_TCP  = 6,
149         IPPROTO_UDP  = 17
150     }
151 
152     const uint INADDR_ANY       = 0x00000000;
153     const uint INADDR_BROADCAST = 0xffffffff;
154 }
155 
156 
157 //
158 // IPV6 (IP6)
159 //
160 /*
161 NOTE: The following must must be defined in tango.stdc.posix.arpa.inet to break
162       a circular import: INET6_ADDRSTRLEN.
163 
164 struct in6_addr
165 {
166     uint8_t[16] s6_addr;
167 }
168 
169 struct sockaddr_in6
170 {
171     sa_family_t sin6_family;
172     in_port_t   sin6_port;
173     uint32_t    sin6_flowinfo;
174     in6_addr    sin6_addr;
175     uint32_t    sin6_scope_id;
176 }
177 
178 extern in6_addr in6addr_any;
179 extern in6_addr in6addr_loopback;
180 
181 struct ipv6_mreq
182 {
183     in6_addr    ipv6mr_multiaddr;
184     uint        ipv6mr_interface;
185 }
186 
187 IPPROTO_IPV6
188 
189 INET6_ADDRSTRLEN
190 
191 IPV6_JOIN_GROUP
192 IPV6_LEAVE_GROUP
193 IPV6_MULTICAST_HOPS
194 IPV6_MULTICAST_IF
195 IPV6_MULTICAST_LOOP
196 IPV6_UNICAST_HOPS
197 IPV6_V6ONLY
198 
199 // macros
200 int IN6_IS_ADDR_UNSPECIFIED(in6_addr*)
201 int IN6_IS_ADDR_LOOPBACK(in6_addr*)
202 int IN6_IS_ADDR_MULTICAST(in6_addr*)
203 int IN6_IS_ADDR_LINKLOCAL(in6_addr*)
204 int IN6_IS_ADDR_SITELOCAL(in6_addr*)
205 int IN6_IS_ADDR_V4MAPPED(in6_addr*)
206 int IN6_IS_ADDR_V4COMPAT(in6_addr*)
207 int IN6_IS_ADDR_MC_NODELOCAL(in6_addr*)
208 int IN6_IS_ADDR_MC_LINKLOCAL(in6_addr*)
209 int IN6_IS_ADDR_MC_SITELOCAL(in6_addr*)
210 int IN6_IS_ADDR_MC_ORGLOCAL(in6_addr*)
211 int IN6_IS_ADDR_MC_GLOBAL(in6_addr*)
212 */
213 
214 version ( linux )
215 {
216     struct in6_addr
217     {
218         union
219         {
220             uint8_t[16] s6_addr;
221             uint16_t[8] s6_addr16;
222             uint32_t[4] s6_addr32;
223         }
224     }
225 
226     struct sockaddr_in6
227     {
228         sa_family_t sin6_family;
229         in_port_t   sin6_port;
230         uint32_t    sin6_flowinfo;
231         in6_addr    sin6_addr;
232         uint32_t    sin6_scope_id;
233     }
234 
235     extern in6_addr in6addr_any;
236     extern in6_addr in6addr_loopback;
237 
238     struct ipv6_mreq
239     {
240         in6_addr    ipv6mr_multiaddr;
241         uint        ipv6mr_interface;
242     }
243 
244     enum : uint
245     {
246         IPPROTO_IPV6        = 41,
247 
248         INET6_ADDRSTRLEN    = 46,
249 
250         IPV6_JOIN_GROUP     = 20,
251         IPV6_LEAVE_GROUP    = 21,
252         IPV6_MULTICAST_HOPS = 18,
253         IPV6_MULTICAST_IF   = 17,
254         IPV6_MULTICAST_LOOP = 19,
255         IPV6_UNICAST_HOPS   = 16,
256         IPV6_V6ONLY         = 26
257     }
258 
259     // macros
260     extern (D) int IN6_IS_ADDR_UNSPECIFIED( in6_addr* addr )
261     {
262         return (cast(uint32_t*) addr)[0] == 0 &&
263                (cast(uint32_t*) addr)[1] == 0 &&
264                (cast(uint32_t*) addr)[2] == 0 &&
265                (cast(uint32_t*) addr)[3] == 0;
266     }
267 
268     extern (D) int IN6_IS_ADDR_LOOPBACK( in6_addr* addr )
269     {
270         return (cast(uint32_t*) addr)[0] == 0  &&
271                (cast(uint32_t*) addr)[1] == 0  &&
272                (cast(uint32_t*) addr)[2] == 0  &&
273                (cast(uint32_t*) addr)[3] == htonl( 1 );
274     }
275 
276     extern (D) int IN6_IS_ADDR_MULTICAST( in6_addr* addr )
277     {
278         return (cast(uint8_t*) addr)[0] == 0xff;
279     }
280 
281     extern (D) int IN6_IS_ADDR_LINKLOCAL( in6_addr* addr )
282     {
283         return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfe800000 );
284     }
285 
286     extern (D) int IN6_IS_ADDR_SITELOCAL( in6_addr* addr )
287     {
288         return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfec00000 );
289     }
290 
291     extern (D) int IN6_IS_ADDR_V4MAPPED( in6_addr* addr )
292     {
293         return (cast(uint32_t*) addr)[0] == 0 &&
294                (cast(uint32_t*) addr)[1] == 0 &&
295                (cast(uint32_t*) addr)[2] == htonl( 0xffff );
296     }
297 
298     extern (D) int IN6_IS_ADDR_V4COMPAT( in6_addr* addr )
299     {
300         return (cast(uint32_t*) addr)[0] == 0 &&
301                (cast(uint32_t*) addr)[1] == 0 &&
302                (cast(uint32_t*) addr)[2] == 0 &&
303                ntohl( (cast(uint32_t*) addr)[3] ) > 1;
304     }
305 
306     extern (D) int IN6_IS_ADDR_MC_NODELOCAL( in6_addr* addr )
307     {
308         return IN6_IS_ADDR_MULTICAST( addr ) &&
309                ((cast(uint8_t*) addr)[1] & 0xf) == 0x1;
310     }
311 
312     extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( in6_addr* addr )
313     {
314         return IN6_IS_ADDR_MULTICAST( addr ) &&
315                ((cast(uint8_t*) addr)[1] & 0xf) == 0x2;
316     }
317 
318     extern (D) int IN6_IS_ADDR_MC_SITELOCAL( in6_addr* addr )
319     {
320         return IN6_IS_ADDR_MULTICAST(addr) &&
321                ((cast(uint8_t*) addr)[1] & 0xf) == 0x5;
322     }
323 
324     extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( in6_addr* addr )
325     {
326         return IN6_IS_ADDR_MULTICAST( addr) &&
327                ((cast(uint8_t*) addr)[1] & 0xf) == 0x8;
328     }
329 
330     extern (D) int IN6_IS_ADDR_MC_GLOBAL( in6_addr* addr )
331     {
332         return IN6_IS_ADDR_MULTICAST( addr ) &&
333                ((cast(uint8_t*) addr)[1] & 0xf) == 0xe;
334     }
335 }
336 version ( solaris )
337 {
338     struct in6_addr
339     {
340         union
341         {
342             uint8_t[16] s6_addr;
343             uint32_t[4] s6_addr32;
344 			uint32_t	__S6_align;
345         }
346     }
347 
348     struct sockaddr_in6
349     {
350         sa_family_t sin6_family;
351         in_port_t   sin6_port;
352         uint32_t    sin6_flowinfo;
353         in6_addr    sin6_addr;
354         uint32_t    sin6_scope_id;
355 		uint32_t	__sin6_src_id;	/* Impl. specific - UDP replies */
356     }
357 
358     extern in6_addr in6addr_any;
359     extern in6_addr in6addr_loopback;
360 
361     struct ipv6_mreq
362     {
363         in6_addr    ipv6mr_multiaddr;
364         uint        ipv6mr_interface;
365     }
366 
367     enum : uint
368     {
369         IPPROTO_IPV6        = 41,
370 
371         INET6_ADDRSTRLEN    = 46,
372 
373         IPV6_JOIN_GROUP     = 0x9,
374         IPV6_LEAVE_GROUP    = 0xa,
375         IPV6_MULTICAST_HOPS = 0x7,
376         IPV6_MULTICAST_IF   = 0x6,
377         IPV6_MULTICAST_LOOP = 0x8,
378         IPV6_UNICAST_HOPS   = 0x5,
379         IPV6_V6ONLY         = 0x27
380     }
381 
382     // macros
383     extern (D) int IN6_IS_ADDR_UNSPECIFIED( in6_addr* addr )
384     {
385         return addr.s6_addr32[3] == 0 &&
386                addr.s6_addr32[2] == 0 &&
387                addr.s6_addr32[1] == 0 &&
388                addr.s6_addr32[0] == 0;
389     }
390 
391   version(BigEndian)
392   {
393     extern (D) int IN6_IS_ADDR_LOOPBACK( in6_addr* addr )
394     {
395 		version(BigEndian)	enum : uint { N = 0x00000001 }
396 		else				enum : uint { N = 0x01000000 }
397 
398         return addr.s6_addr32[3] == N &&
399                addr.s6_addr32[2] == 0 &&
400                addr.s6_addr32[1] == 0 &&
401                addr.s6_addr32[0] == 0;
402     }
403   }
404 
405 	//
406 	// Note to tango devs:
407 	//   These macros seem alot more efficient then the Linux ones!
408 	//
409 
410     extern (D) int IN6_IS_ADDR_MULTICAST( in6_addr* addr )
411     {
412 		version(BigEndian)
413         	return (addr.s6_addr32[0] & 0xff000000) == 0xff000000;
414 		else
415 			return (addr.s6_addr32[0] & 0x000000ff) == 0x000000ff;
416     }
417 
418     extern (D) int IN6_IS_ADDR_LINKLOCAL( in6_addr* addr )
419     {
420 		version(BigEndian)
421         	return (addr.s6_addr32[0] & 0xffc00000) == 0xfe800000;
422 		else
423 			return (addr.s6_addr32[0] & 0x0000c0ff) == 0x000080fe;
424     }
425 
426     extern (D) int IN6_IS_ADDR_SITELOCAL( in6_addr* addr )
427     {
428 		version(BigEndian)
429         	return (addr.s6_addr32[0] & 0xffc00000) == 0xfec00000;
430 		else
431 			return (addr.s6_addr32[0] & 0x0000c0ff) == 0x0000c0fe;
432     }
433 
434     extern (D) int IN6_IS_ADDR_V4MAPPED( in6_addr* addr )
435     {
436 		version(BigEndian)	enum : uint { N = 0x0000ffff }
437 		else				enum : uint { N = 0xffff0000 }
438 
439 		return addr.s6_addr32[2] == N &&
440                addr.s6_addr32[1] == 0 &&
441                addr.s6_addr32[0] == 0;
442     }
443 
444     extern (D) int IN6_IS_ADDR_V4COMPAT( in6_addr* addr )
445     {
446 		version(BigEndian)	enum : uint { N = 0x00000001 }
447 		else				enum : uint { N = 0x01000000 }
448 
449 		return addr.s6_addr32[2] == 0 &&
450                addr.s6_addr32[1] == 0 &&
451                addr.s6_addr32[0] == 0 &&
452                addr.s6_addr32[3] != 0 &&
453                addr.s6_addr32[3] != N;
454     }
455 
456     extern (D) int IN6_IS_ADDR_MC_NODELOCAL( in6_addr* addr )
457     {
458 		version(BigEndian)
459         	return (addr.s6_addr32[0] & 0xff0f0000) == 0xff010000;
460 		else
461 			return (addr.s6_addr32[0] & 0x00000fff) == 0x000001ff;
462     }
463 
464     extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( in6_addr* addr )
465     {
466         version(BigEndian)
467         	return (addr.s6_addr32[0] & 0xff0f0000) == 0xff020000;
468 		else
469 			return (addr.s6_addr32[0] & 0x00000fff) == 0x000002ff;
470     }
471 
472     extern (D) int IN6_IS_ADDR_MC_SITELOCAL( in6_addr* addr )
473     {
474         version(BigEndian)
475         	return (addr.s6_addr32[0] & 0xff0f0000) == 0xff050000;
476 		else
477 			return (addr.s6_addr32[0] & 0x00000fff) == 0x000005ff;
478     }
479 
480     extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( in6_addr* addr )
481     {
482         version(BigEndian)
483         	return (addr.s6_addr32[0] & 0xff0f0000) == 0xff080000;
484 		else
485 			return (addr.s6_addr32[0] & 0x00000fff) == 0x000008ff;
486     }
487 
488     extern (D) int IN6_IS_ADDR_MC_GLOBAL( in6_addr* addr )
489     {
490         version(BigEndian)
491         	return (addr.s6_addr32[0] & 0xff0f0000) == 0xff0e0000;
492 		else
493 			return (addr.s6_addr32[0] & 0x00000fff) == 0x00000eff;
494     }
495 }
496 
497 
498 //
499 // Raw Sockets (RS)
500 //
501 /*
502 IPPROTO_RAW
503 */
504 
505 version ( linux )
506 {
507     const uint IPPROTO_RAW = 255;
508 }
509 else version ( solaris )
510 {
511     const uint IPPROTO_RAW = 255;
512 }