1 
2 /* ********************************************************************	*
3  * ni_funct.h	version 0.04 3-7-09					*
4  *									*
5  *     COPYRIGHT 2008-2009 Michael Robinton <michael@bizsystems.com>	*
6  *									*
7  * This program is free software; you can redistribute it and/or modify	*
8  * it under the terms of either:					*
9  *									*
10  *  a) the GNU General Public License as published by the Free		*
11  *  Software Foundation; either version 2, or (at your option) any	*
12  *  later version, or							*
13  *									*
14  *  b) the "Artistic License" which comes with this distribution.	*
15  *									*
16  * This program is distributed in the hope that it will be useful,	*
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of	*
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See either	*
19  * the GNU General Public License or the Artistic License for more 	*
20  * details.								*
21  *									*
22  * You should have received a copy of the Artistic License with this	*
23  * distribution, in the file named "Artistic".  If not, I'll be glad 	*
24  * to provide one.							*
25  *									*
26  * You should also have received a copy of the GNU General Public 	*
27  * License along with this program in the file named "Copying". If not, *
28  * write to the 							*
29  *									*
30  *	Free Software Foundation, Inc.					*
31  *	59 Temple Place, Suite 330					*
32  *	Boston, MA  02111-1307, USA					*
33  *									*
34  * or visit their web page on the internet at:				*
35  *									*
36  *	http://www.gnu.org/copyleft/gpl.html.				*
37  * ********************************************************************	*/
38 
39 #ifndef _NI_FUNC_H
40 #define _NI_FUNC_H 1
41 
42 #ifndef _NI_FIXUPS_H
43 #error NEED 'ni_fixups' first
44 #endif
45 
46 /* **************************************************** *
47  *	checking and printing the MAC address		*
48  * **************************************************** */
49 
50 #define NI_PRINT_MAC(__macp) printf("MAC addr %02X:%02X:%02X:%02X:%02X:%02X", \
51             (u_char)__macp[0],(u_char)__macp[1],(u_char)__macp[2], \
52             (u_char)__macp[3],(u_char)__macp[4],(u_char)__macp[5])
53 
54 #define NI_MAC_NOT_ZERO(__macp) (((u_int32_t *)(__macp))[0] != 0 || ((u_int16_t *)(__macp))[2] != 0)
55 
56 /* **************************************************** *
57  *		text table definition			*
58  * **************************************************** */
59 
60 typedef struct ni_IFF_table_entry {
61 	u_int64_t	iff_val;
62 	char		*iff_nam;
63 } ni_iff_t;
64 
65 /* **************************************************** *
66  *	print ipV6 address - full length		*
67  * **************************************************** */
68 #ifdef LOCAL_SIZEOF_SOCKADDR_IN6
69 #define NI_PRINT_IPV6(__sin6_addr) \
70 	printf("%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X", \
71 		(__sin6_addr).s6_addr[0], \
72 		(__sin6_addr).s6_addr[1], \
73 		(__sin6_addr).s6_addr[2], \
74 		(__sin6_addr).s6_addr[3], \
75 		(__sin6_addr).s6_addr[4], \
76 		(__sin6_addr).s6_addr[5], \
77 		(__sin6_addr).s6_addr[6], \
78 		(__sin6_addr).s6_addr[7], \
79 		(__sin6_addr).s6_addr[8], \
80 		(__sin6_addr).s6_addr[9], \
81 		(__sin6_addr).s6_addr[10], \
82 		(__sin6_addr).s6_addr[11], \
83 		(__sin6_addr).s6_addr[12], \
84 		(__sin6_addr).s6_addr[13], \
85 		(__sin6_addr).s6_addr[14], \
86 		(__sin6_addr).s6_addr[15])
87 #endif
88 
89 /* **************************************************** *
90  *	free the appropriate mememory for getifaddrs	*
91  * **************************************************** */
92 
93 void
94 ni_free_gifa(struct ifaddrs * ifap, int flavor);
95 
96 /* **************************************************** *
97  *	local multi-platform get_ifaddrs function	*
98  * **************************************************** */
99 
100 int
101 ni_getifaddrs(struct ifaddrs **ifap, int flavor);
102 
103 /* **************************************************** *
104  *	conditionally close and reopen socket		*
105  * **************************************************** */
106 int
107 ni_clos_reopn_dgrm(int fd, u_int af);
108 
109 
110 /* **************************************************** *
111  *	allocate memory for a duplicate of the		*
112  *	memory chunck at 'memp' of 'size' and		*
113  * 	return a pointer. MUST free(newptr)		*
114  *	On error returns NULL and sets ENOMEM		*
115  * **************************************************** */
116 
117 void *
118 ni_memdup(void * memp, int size);
119 
120 /* **************************************************** *
121  *      generate a netmask from a prefix length         *
122  * **************************************************** */
123 
124 void
125 ni_plen2mask(void * in_addr, int plen, int sizeofaddr);
126 
127 /* ****************************************************	*
128  *	calculate the length of netmask prefix		*
129  * ****************************************************	*/
130 /*	pointer to bytes, size in bytes of address	*/
131 
132 int
133 ni_prefix(void * ap, int sz);
134 
135 /* **************************************************** *
136  * some OS lose scope on the particular device/addr     *
137  * handle when certain ioctl's are performed. this      *
138  * function refreshs the ifconf chain and positions     *
139  * the pointers in the exact same spot with fresh scope *
140  * **************************************************** */
141 
142 struct ni_ifconf_flavor;
143 
144 int
145 ni_refresh_ifreq(int fd, struct ifconf * ifc, void ** ifr, void ** lifr, struct ni_ifconf_flavor * nip);
146 
147 /* **************************************************** *
148  *	define access to various types of fields	*
149  *	in 'ifreq', 'in6_ifreq', and 'lifreq'		*
150  *	structures					*
151  * **************************************************** */
152 
153 /* ******************************************** *
154  *   function to return MAC address if it	*
155  *   is not present in a DL or LL record	*
156  * ******************************************** */
157 
158 unsigned char *
159 ni_fallbackhwaddr(u_int af, void * ifr);
160 
161 /* ******************************************** *
162  *   the semi-standard version of getifaddrs    *
163  * ******************************************** */
164 
165 int
166 nifreq_gifaddrs(struct ifaddrs **ifap, struct ni_ifconf_flavor * nifp);
167 
168 /* a sane amount of memory for interface descriptors	*/
169 #define NI_IFREQ_MEM_MAX 1048576
170 
171 struct nifreq {
172 	char	ni_ifr_name[IFNAMSIZ];
173 	union {
174 		struct	sockaddr	 ifr_saddr;
175 		struct	sockaddr_in	 ifr_sin;
176 		struct	sockaddr_storage ifr_stor;
177 #ifdef LOCAL_SIZEOF_SOCKADDR_IN6
178 		struct	sockaddr_in6	 ifr_sin6;
179 #endif
180 		short			 ifr_short;
181 		unsigned short		 ifr_ushort;
182 		int			 ifr_int;
183 		char			 ifr_char[2];
184 /*	this is really a char *		*/
185 		caddr_t			 ifr_cadt_data;
186 		unsigned char		 ifr_uchar[2];
187 		int			 ifr_iary[2];
188 		unsigned int		 ifr_uint;
189 		u_int32_t		 ifr_uint32;
190 		u_int64_t		 ifr_uint64;
191 		u_int32_t		 ifr_uiary[2];
192 #ifdef HAVE_STRUCT_IN6_IFREQ
193 		struct in6_addrlifetime  ifru_lifetime;
194 		struct in6_ifstat 	 ifru_stat;
195 		struct icmp6_ifstat 	 ifru_icmp6stat;
196 #endif
197 #ifdef HAVE_STRUCT_LIFREQ
198 		char lifreq_pad[NI_LIFREQ_PAD];
199 #endif
200 	} ni_ifru;
201 
202 /*	convenience definitions		*/
203 #
204 #define ni_saddr	ni_ifru.ifr_saddr	/* any sockaddr		*/
205 #define ni_sin		ni_ifru.ifr_sin		/* any sockaddr_in	*/
206 #define ni_stor		ni_ifru.ifr_stor	/* and sockaddr_storage	*/
207 #ifdef LOCAL_SIZEOF_SOCKADDR_IN6
208 # define ni_sin6	ni_ifru.ifr_sin6	/* any sockaddr_in6	*/
209 #endif
210 #define ni_short	ni_ifru.ifr_short	/* any short		*/
211 #define ni_ushort	ni_ifru.ifr_ushort	/* any unsigned short	*/
212 #define ni_int		ni_ifru.ifr_int		/* any int		*/
213 #define ni_char		ni_ifru.ifr_char	/* any char array	*/
214 #define ni_data		ni_ifru.ifr_cadt_data	/* device specific data pointer	*/
215 #define ni_uchar	ni_ifru.ifr_uchar	/* any unsigned char array - hardware mac	*/
216 #define ni_iary		ni_ifru.ifr_iary	/* any int array	*/
217 #define ni_uint		ni_ifru.ifr_uint	/* any uint		*/
218 #define ni_uint32	ni_ifru.ifr_uint32	/* any uint32		*/
219 #define ni_uint64	ni_ifru.ifr_uint64	/* any uint64		*/
220 #define ni_uiary	ni_ifru.ifr_uiary	/* any uint32 array	*/
221 #ifdef HAVE_STRUCT_IN6_IFREQ
222 # define ni_lifetime	ni_ifru.ifru_lifetime
223 # define ni_stat	ni_ifru.ifru_stat
224 # define ni_icmp6	ni_ifru.ifru_icmp6stat
225 #endif
226 };
227 
228 /* ****************************************************	*
229  *	standard SIOCget functions			*
230  *							*
231  *	execute supported ioctl's			*
232  *	where a value is requested, return it		*
233  *	otherwise it is up to the user to retireve	*
234  *	information via their pointers			*
235  *	returns -1 on error, sets errno			*
236  * ****************************************************	*/
237 
238 int32_t
239 ni_get_any(int fd, int cmd, void * ifr);
240 
241 /* ****************************************************	*
242  *	standard SIOCset functions			*
243  *							*
244  *	execute supported ioctl's			*
245  *	returns -1 on error, sets errno			*
246  *							*
247  *	struct nifreq ifr should be prepared, for	*
248  *	add/modify of a Linux  ipV6 address, the 	*
249  *	PREFIX/CIDR value should be stored at:		*
250  *							*
251  *		ifr->ni_sin6.sin6_port			*
252  *							*
253  * ****************************************************	*/
254 
255 int
256 ni_set_any(int fd, int cmd, struct nifreq * ifr);
257 
258 #ifdef LOCAL_SIZEOF_SOCKADDR_IN6
259 
260 /* ********************************************	*
261  *	get scope id from struct scope index	*
262  *	or KAME bits, correct bits as needed	*
263  * ********************************************	*/
264 
265 u_int
266 ni_get_scopeid(struct sockaddr_in6 * sin6);
267 
268 #endif
269 
270 /* ********************************************	*
271  *	IPV6_ADDR_xxxx definitions from		*
272  *	linux kernel	include/net/ipv6.h	*
273  *	these are the bits for the byte in	*
274  *		/proc/net/if_net6		*
275  * ********************************************	*
276  *
277  * with credits to kernel and USAGI developer team
278  * basic information was taken from "kernel/include/net/ipv6.h"
279  *
280 
281  *	Addr type
282  *
283  *	type	-	unicast | multicast | anycast
284  *	scope	-	local	| site	    | global
285  *	v4	-	compat
286  *	v4mapped
287  *	any
288  *	loopback
289  */
290 
291 /*
292  *	make sure and include changes to this table in the
293  *	_lx_types function in Interfaces.xs
294  */
295 
296 #define IPV6_ADDR_ANY			(u_int32_t) 0x0000u
297 #define IPV6_ADDR_UNICAST		(u_int32_t) 0x0001u
298 #define IPV6_ADDR_MULTICAST		(u_int32_t) 0x0002u
299 #define IPV6_ADDR_ANYCAST		(u_int32_t) 0x0004u
300 #define IPV6_ADDR_LOOPBACK		(u_int32_t) 0x0010u
301 #define IPV6_ADDR_LINKLOCAL		(u_int32_t) 0x0020u
302 #define IPV6_ADDR_SITELOCAL		(u_int32_t) 0x0040u
303 #define IPV6_ADDR_COMPATv4		(u_int32_t) 0x0080u
304 #define IPV6_ADDR_SCOPE_MASK		(u_int32_t) 0x00f0u
305 #define IPV6_ADDR_MAPPED		(u_int32_t) 0x1000u
306 #define IPV6_ADDR_RESERVED		(u_int32_t) 0x2000u	/* reserved address space */
307 #define IPV6_ADDR_ULUA			(u_int32_t) 0x4000u	/* Unique Local Unicast Address */
308 #define IPV6_ADDR_6TO4			(u_int32_t) 0x00010000u
309 #define IPV6_ADDR_6BONE			(u_int32_t) 0x00020000u
310 #define IPV6_ADDR_AGU			(u_int32_t) 0x00040000u
311 #define IPV6_ADDR_UNSPECIFIED		(u_int32_t) 0x00080000u
312 #define IPV6_ADDR_SOLICITED_NODE	(u_int32_t) 0x00100000u
313 #define IPV6_ADDR_ISATAP		(u_int32_t) 0x00200000u	/* RFC 4214 */
314 #define IPV6_ADDR_PRODUCTIVE		(u_int32_t) 0x00400000u
315 #define IPV6_ADDR_6TO4_MICROSOFT	(u_int32_t) 0x00800000u
316 #define IPV6_ADDR_TEREDO		(u_int32_t) 0x01000000u	/* RFC 4380 */
317 #define IPV6_ADDR_ORCHID		(u_int32_t) 0x02000000u /* RFC 4843 */
318 #define IPV6_ADDR_NON_ROUTE_DOC		(u_int32_t) 0x08000000u	/* RFC 3849 */
319 
320 /* ****************************************************	*
321  *   return size of format table for linux_scope2txt	*
322  * ****************************************************	*/
323 
324 int
325 ni_sizeof_type2txt();
326 
327 /* ****************************************************	*
328  *	This function maps I<Linux> style scope 	*
329  *	bits to their RFC-2373 equivalent.		*
330  *							*
331  *  scope flags	rfc-2373				*
332  *	0 	reserved				*
333  *	1    node-local (aka loopback, interface-local)	*
334  *	2    link-local					*
335  *	3	unassigned				*
336  *	4	unassigned				*
337  *	5    site-local					*
338  *	6	unassigned				*
339  *	7	unassigned				*
340  *	8    organization-local				*
341  *	9	unassigned				*
342  *	A	unassigned				*
343  *	B	unassigned				*
344  *	C	unassigned				*
345  *	D	unassigned				*
346  *	E    global scope				*
347  *	F	reserved				*
348  *							*
349  *    Linux   rfc-2373					*
350  *   0x0000	0xe	GLOBAL				*
351  *   0x0010u	0x1 NODELOCAL, LOOPBACK, INTERFACELOCAL	*
352  *   0x0020u	0x2	LINKLOCAL			*
353  *   0x0040u	0x5	SITELOCAL			*
354  *   0x0080u is mapped out of range to 0x10		*
355  * ****************************************************	*/
356 
357 int
358 ni_lx_type2scope(int lscope);
359 
360 /* ****************************************************	*
361  *	      value definitions for above		*
362  * ****************************************************	*/
363 
364 #define RFC2373_GLOBAL		0xeu
365 #define RFC2373_ORGLOCAL	0x8u
366 #define RFC2373_SITELOCAL	0x5u
367 #define RFC2373_LINKLOCAL	0x2u
368 #define RFC2373_NODELOCAL	0x1u
369 #define LINUX_COMPATv4		0x10u
370 
371 /* ****************************************************	*
372  *    print statement for internal linux format flags	*
373  * ****************************************************	*/
374 
375 void
376 ni_linux_scope2txt(u_int32_t flags);
377 
378 /* ****************************************************	*
379  *    returns attribute bits for extended linux scope	*
380  * ****************************************************	*/
381 
382 u_int32_t
383 ni_in6_classify(unsigned char * s6_bytes);
384 
385 /* ****************************************************	*
386  *	support for variants of ifreq			*
387  * ****************************************************	*/
388 
389 /*
390  *	    IF / WHEN YOU CHANGE THIS STRUCT,
391  *	UPDATE IT IN THE SUPPORTED FLAVOR MODULES!
392  *
393  * Currently support flavors:
394  */
395 
396 enum ni_FLAVOR {
397 	NI_NULL,
398 	NI_IFREQ,
399 	NI_LIFREQ,
400 	NI_IN6_IFREQ,
401 	NI_LINUXPROC
402 };
403 
404 static int
405 developer(void * ifr);
406 
407 struct ni_ifconf_flavor {
408     enum ni_FLAVOR 		ni_type;
409     int				siocgifindex;
410     int				siocsifaddr;
411     int				siocgifaddr;
412     int				siocdifaddr;
413     int				siocaifaddr;
414     int				siocsifdstaddr;
415     int				siocgifdstaddr;
416     int				siocsifflags;
417     int				siocgifflags;
418     int				siocsifmtu;
419     int				siocgifmtu;
420     int				siocsifbrdaddr;
421     int				siocgifbrdaddr;
422     int				siocsifnetmask;
423     int				siocgifnetmask;
424     int				siocsifmetric;
425     int				siocgifmetric;
426     int				ifr_offset;
427     int				(*gifaddrs)(struct ifaddrs **ifap, struct ni_ifconf_flavor * nifp);
428     void			(*fifaddrs)(struct ifaddrs *ifa);
429     int				(*refreshifr)(int fd, struct ifconf * ifc, void ** oifr, void ** olifr, struct ni_ifconf_flavor * nip);
430     void *			(*getifreqs)(int fd, void * ifc);
431     int				(*developer)(void * whatever);
432     struct ni_ifconf_flavor * 	ni_ifcf_next;
433 };
434 
435 struct ni_ifconf_flavor *
436 ni_ifcf_get(enum ni_FLAVOR type);
437 
438 /* return flavor pointer for NI_IFREQ if flavor is unknown	*/
439 struct ni_ifconf_flavor *
440 ni_safe_ifcf_get(enum ni_FLAVOR type);
441 
442 void
443 ni_ifcf_register(struct ni_ifconf_flavor * nip);
444 
445 struct ni_af_flavor;
446 struct ni_af_flavor {
447     int				ni_af_family;
448     int32_t			(*af_get_any)(int fd, int cmd, void * ifr);
449     int				(*af_getifaddrs)(int fd, struct ifaddrs * thisif, struct nifreq * ifr,...);
450     struct ni_af_flavor *	ni_aff_next;
451 };
452 
453 struct ni_af_flavor *
454 ni_af_get(int af);
455 
456 void
457 ni_af_register(struct ni_af_flavor * nafp);
458 
459 /* ************************************************************	*
460  *	Certain broken Solaris headers cause build		*
461  *	errors with the syntax for constructors.		*
462  *  i.e.							*
463  *	void __attribute__((constructor))			*
464  *	constructor_function () 				*
465  *	{							*
466  *		code....					*
467  *	};							*
468  *								*
469  * line 249: syntax error before or at: (			*
470  * line 251: warning: old-style declaration or incorrect type	*
471  * cc: acomp failed [filename.c]				*
472  * *** Error code 2						*
473  * make: Fatal error: Command failed for target 'filename.o'	*
474  *								*
475  *	The various constructors are declared here and called	*
476  *	during module load as a work-around to this problem	*
477  * ************************************************************	*/
478 
479 void ni_ifreq_ctor();
480 void ni_in6_ifreq_ctor();
481 void ni_lifreq_ctor();
482 void ni_linuxproc_ctor();
483 
484 /* ****************************************************	*
485  *	developer support, not for production		*
486  * ****************************************************	*/
487 
488 int
489 ni_developer(enum ni_FLAVOR type);
490 
491 void
492 ni_getifaddrs_dump(int flavor, struct ifaddrs * ifap);
493 
494 #endif
495