1 /* Common include file
2  *
3  * Copyright (C) 2001-2005  Carsten Schill <carsten@cschill.de>
4  * Copyright (C) 2006-2009  Julien BLACHE <jb@jblache.org>
5  * Copyright (C) 2009       Todd Hayton <todd.hayton@gmail.com>
6  * Copyright (C) 2009-2011  Micha Lenk <micha@debian.org>
7  * Copyright (C) 2011-2013  Joachim Nilsson <troglobit@gmail.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
22  */
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdarg.h>
28 #include <syslog.h>
29 #include <errno.h>
30 #include <unistd.h>
31 
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 
36 #include <sys/ioctl.h>
37 #include <sys/socket.h>
38 #include <sys/un.h>
39 #include <sys/queue.h>
40 
find_valid_iface(const char * ifname,int cmd)41 #include <net/if.h>
42 
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
45 
46 #include "config.h"
47 
48 #ifdef HAVE_LINUX_MROUTE_H
49 #define _LINUX_IN_H             /* For Linux <= 2.6.25 */
50 #include <linux/types.h>
51 #include <linux/mroute.h>
52 #endif
53 
54 #ifdef HAVE_LINUX_MROUTE6_H
55 #include <linux/mroute6.h>
56 #endif
57 
58 #ifdef HAVE_LINUX_FILTER_H
59 #include <linux/filter.h>
60 #endif
61 
62 #ifdef HAVE_NET_ROUTE_H
63 #include <net/route.h>
64 #endif
65 
66 #ifdef HAVE_NETINET_IP_MROUTE_H
67 #include <netinet/ip_mroute.h>
68 #endif
69 #ifdef __DragonFly__
70 #include <net/ip_mroute/ip_mroute.h>
71 #endif
72 
73 #ifdef HAVE_NETINET6_IP6_MROUTE_H
74 #ifdef HAVE_SYS_PARAM_H
75 #include <sys/param.h>
76 #endif
77 #include <netinet6/ip6_mroute.h>
78 #endif
79 
80 typedef u_int8_t uint8;
81 typedef u_int16_t uint16;
mcgroup_join_leave_ipv4(int sd,int cmd,const char * ifname,struct in_addr group)82 typedef u_int32_t uint32;
83 
84 #define SA(x)   ((struct sockaddr *)x)
85 #define SIN4(x) ((struct sockaddr_in *)x)
86 #define SIN6(x) ((struct sockaddr_in6 *)x)
87 
88 #ifndef IN6_IS_ADDR_MULTICAST
89 #define IN6_IS_ADDR_MULTICAST(a) (((__const uint8_t *) (a))[0] == 0xff)
90 #endif
91 
92 #ifndef MIN
93 #define MIN(a, b) ((a) < (b) ? (a) : (b))
94 #endif
95 #ifndef MAX
96 #define MAX(a, b) ((a) < (b) ? (b) : (a))
97 #endif
98 
99 /* http://stackoverflow.com/questions/1598773/is-there-a-standard-function-in-c-that-would-return-the-length-of-an-array/1598827#1598827
100  * Evidently Google uses it in Chromium.  It is actually intended to look like 0[arr], read the link, or search the web.
101  */
102 #define ARRAY_ELEMENTS(arr) ((sizeof(arr)/sizeof(0[arr])) / ((size_t)(!(sizeof(arr) % sizeof(0[arr])))))
103 
104 struct iface {
105 	char name[IFNAMSIZ + 1];
106 	struct in_addr inaddr;	/* == 0 for non IP interfaces */
107 	u_short ifindex;	/* Physical interface index   */
108 	short flags;
109 	short vif;
mcgroup4_join(const char * ifname,struct in_addr group)110 	short mif;
111 	uint8_t threshold;	/* TTL threshold: 1-255, default: 1 */
112 };
113 
114 extern int do_vifs;
115 extern int do_syslog;
116 
117 /* ifvc.c */
118 #define MAX_IF         40	// max. number of interfaces recognized
119 
120 void          iface_init            (void);
121 struct iface *iface_find_by_name    (const char *ifname);
122 struct iface *iface_find_by_index   (unsigned int ifindex);
mcgroup4_leave(const char * ifname,struct in_addr group)123 struct iface *iface_find_by_vif     (int vif);
124 int           iface_get_vif         (struct iface *iface);
125 int           iface_get_mif         (struct iface *iface);
126 int           iface_get_vif_by_name (const char *ifname);
127 int           iface_get_mif_by_name (const char *ifname);
128 
129 /* mroute-api.c */
130 
131 /*
132  * IPv4 multicast route
mcgroup4_disable(void)133  */
134 #define MAX_MC_VIFS MAXVIFS		/* from linux/mroute.h */
135 
136 struct mroute4 {
137 	LIST_ENTRY(mroute4) link;
138 
139 	struct in_addr sender;
140 	struct in_addr group;           /* multicast group */
141 	short inbound;                  /* incoming VIF    */
142 	uint8 ttl[MAX_MC_VIFS];         /* outgoing VIFs   */
143 };
mcgroup6_init(void)144 typedef struct mroute4 mroute4_t;
145 
146 /*
147  * IPv6 multicast route
148  */
149 #ifdef HAVE_IPV6_MULTICAST_ROUTING
150 #define MAX_MC_MIFS MAXMIFS		/* from linux/mroute6.h */
151 #else
152 #define MAX_MC_MIFS 1			/* Dummy value for builds w/o IPv6 routing */
153 #endif
154 
155 struct mroute6 {
156 	struct sockaddr_in6 sender;
157 	struct sockaddr_in6 group;      /* multicast group */
158 	short inbound;                  /* incoming VIF    */
159 	uint8 ttl[MAX_MC_MIFS];         /* outgoing VIFs   */
160 };
161 typedef struct mroute6 mroute6_t;
162 
163 /*
164  * Generic multicast route (wrapper for IPv4/IPv6 mroute)
165  */
166 struct mroute {
167 	int version;		/* 4 or 6 */
168 	union {
169 		mroute4_t mroute4;
170 		mroute6_t mroute6;
171 	} u;
mcgroup_join_leave_ipv6(int sd,int cmd,const char * ifname,struct in6_addr group)172 };
173 typedef struct mroute mroute_t;
174 
175 /*
176  * Raw IGMP socket used as interface for the IPv4 mrouted API.
177  * Receives IGMP packets and upcall messages from the kernel.
178  */
179 extern int mroute4_socket;
180 
181 /*
182  * Raw ICMPv6 socket used as interface for the IPv6 mrouted API.
183  * Receives MLD packets and upcall messages from the kenrel.
184  */
185 #define DEFAULT_THRESHOLD 1             /* Packet TTL must be at least 1 to pass */
186 
187 extern int mroute6_socket;
188 
189 int  mroute4_enable  (void);
190 void mroute4_disable (void);
191 int  mroute4_dyn_add (mroute4_t *mroute);
192 int  mroute4_add     (mroute4_t *mroute);
193 int  mroute4_del     (mroute4_t *mroute);
194 
195 int  mroute6_enable  (void);
196 void mroute6_disable (void);
197 int  mroute6_add     (mroute6_t *mroute);
198 int  mroute6_del     (mroute6_t *mroute);
199 
mcgroup6_join(const char * ifname,struct in6_addr group)200 int  mroute_add_vif  (char *ifname, uint8_t threshold);
201 int  mroute_del_vif  (char *ifname);
202 
203 /* ipc.c */
204 int         ipc_server_init (void);
205 struct cmd *ipc_server_read (uint8 buf[], int len);
206 int         ipc_client_init (void);
207 int         ipc_send        (const void *buf, int len);
208 int         ipc_receive     (uint8 buf[], int len);
209 void        ipc_exit        (void);
210 
211 /* cmdpkt.c
212  *
mcgroup6_leave(const char * ifname,struct in6_addr group)213  * XXX: Add example packet layouts
214  */
215 struct cmd {
216 	size_t   len;		/* total size of packet including cmd header */
217 	uint16   cmd;		/* 'a'=Add,'r'=Remove,'j'=Join,'l'=Leave,'k'=Kill */
218 	uint16   count;		/* command argument count */
219 	char    *argv[0]; 	/* 'count' * '\0' terminated strings + '\0' */
220 };
221 
222 #define MX_CMDPKT_SZ 1024	/* command size including appended strings */
223 
mcgroup6_disable(void)224 void       *cmd_build              (char cmd, const char *argv[], int count);
225 const char *cmd_convert_to_mroute  (mroute_t *mroute, const struct cmd *packet);
226 const char *cmd_convert_to_mroute4 (mroute4_t *mroute, const struct cmd *packet);
227 const char *cmd_convert_to_mroute6 (mroute6_t *mroute, const struct cmd *packet);
228 
229 /* mcgroup.c */
230 int  mcgroup4_join    (const char *ifname, struct in_addr  group);
231 int  mcgroup4_leave   (const char *ifname, struct in_addr  group);
232 void mcgroup4_disable (void);
233 int  mcgroup6_join    (const char *ifname, struct in6_addr group);
234 int  mcgroup6_leave   (const char *ifname, struct in6_addr group);
235 void mcgroup6_disable (void);
236 
237 /* log.c */
238 #define LOG_INIT 10
239 
240 extern int  log_level;
241 extern char log_message[128];
242 
243 int loglvl(const char *level);
244 void smclog(int severity, const char *fmt, ...);
245 
246 /* parse-conf.c */
247 int run_script(mroute_t *mroute);
248 int parse_conf_file(const char *file);
249 
250 /* pidfile.c */
251 int pidfile(const char *basename);
252 
253 /**
254  * Local Variables:
255  *  version-control: t
256  *  indent-tabs-mode: t
257  *  c-file-style: "linux"
258  * End:
259  */
260