iptables-1.2.9-2.3.1.src.rpm
[iptables.git] / extensions / libip6t_ROUTE.c
1 /* Shared library add-on to iptables to add ROUTE v6 target support.
2  * Author : Cedric de Launois, <delaunois@info.ucl.ac.be>
3  * v 1.0 2003/06/24
4  */
5
6 #include <stdio.h>
7 #include <string.h>
8 #include <stdlib.h>
9 #include <getopt.h>
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <arpa/inet.h>
13
14 #include <ip6tables.h>
15 #include <linux/netfilter_ipv6/ip6_tables.h>
16 #include <linux/netfilter_ipv6/ip6t_ROUTE.h>
17
18 /* Function which prints out usage message. */
19 static void
20 help(void)
21 {
22         printf(
23 "ROUTE target v%s options:\n"
24 "    --oif   \tifname \t\tRoute the packet through `ifname' network interface\n"
25 "    --gw    \tip     \t\tRoute the packet via this gateway\n"
26 "    --continue\t     \t\tRoute the packet and continue traversing the rules.\n"
27 "\n",
28 "1.0");
29 }
30
31 static struct option opts[] = {
32         { "oif", 1, 0, '1' },
33         { "iif", 1, 0, '2' },
34         { "gw", 1, 0, '3' },
35         { "continue", 0, 0, '4' },
36         { 0 }
37 };
38
39 /* Initialize the target. */
40 static void
41 init(struct ip6t_entry_target *t, unsigned int *nfcache)
42 {
43         struct ip6t_route_target_info *route_info = 
44                 (struct ip6t_route_target_info*)t->data;
45
46         route_info->oif[0] = '\0';
47         route_info->iif[0] = '\0';
48         route_info->gw[0] = 0;
49         route_info->gw[1] = 0;
50         route_info->gw[2] = 0;
51         route_info->gw[3] = 0;
52         route_info->flags = 0;
53 }
54
55
56 #define IP6T_ROUTE_OPT_OIF      0x01
57 #define IP6T_ROUTE_OPT_IIF      0x02
58 #define IP6T_ROUTE_OPT_GW       0x04
59 #define IP6T_ROUTE_OPT_CONTINUE 0x08
60
61 /* Function which parses command options; returns true if it
62    ate an option */
63 static int
64 parse(int c, char **argv, int invert, unsigned int *flags,
65       const struct ip6t_entry *entry,
66       struct ip6t_entry_target **target)
67 {
68         struct ip6t_route_target_info *route_info = 
69                 (struct ip6t_route_target_info*)(*target)->data;
70
71         switch (c) {
72         case '1':
73                 if (*flags & IP6T_ROUTE_OPT_OIF)
74                         exit_error(PARAMETER_PROBLEM,
75                                    "Can't specify --oif twice");
76
77                 if (check_inverse(optarg, &invert, NULL, 0))
78                         exit_error(PARAMETER_PROBLEM,
79                                    "Unexpected `!' after --oif");
80
81                 if (strlen(optarg) > sizeof(route_info->oif) - 1)
82                         exit_error(PARAMETER_PROBLEM,
83                                    "Maximum interface name length %u",
84                                    sizeof(route_info->oif) - 1);
85
86                 strcpy(route_info->oif, optarg);
87                 *flags |= IP6T_ROUTE_OPT_OIF;
88                 break;
89
90         case '2':
91                 exit_error(PARAMETER_PROBLEM,
92                            "--iif option not implemented");
93                 break;
94
95         case '3':
96                 if (*flags & IP6T_ROUTE_OPT_GW)
97                         exit_error(PARAMETER_PROBLEM,
98                                    "Can't specify --gw twice");
99
100                 if (check_inverse(optarg, &invert, NULL, 0))
101                         exit_error(PARAMETER_PROBLEM,
102                                    "Unexpected `!' after --gw");
103
104                 if (!inet_pton(AF_INET6, optarg, (struct in6_addr*)&route_info->gw)) {
105                         exit_error(PARAMETER_PROBLEM,
106                                    "Invalid IPv6 address %s",
107                                    optarg);
108                 }
109
110                 *flags |= IP6T_ROUTE_OPT_GW;
111                 break;
112
113         case '4':
114                 if (*flags & IP6T_ROUTE_OPT_CONTINUE)
115                         exit_error(PARAMETER_PROBLEM,
116                                    "Can't specify --continue twice");
117
118                 route_info->flags |= IP6T_ROUTE_CONTINUE;
119                 *flags |= IP6T_ROUTE_OPT_CONTINUE;
120
121                 break;
122
123         default:
124                 return 0;
125         }
126
127         return 1;
128 }
129
130
131 static void
132 final_check(unsigned int flags)
133 {
134         if (!flags)
135                 exit_error(PARAMETER_PROBLEM,
136                            "ROUTE target: oif or gw option required");
137 }
138
139
140 /* Prints out the targinfo. */
141 static void
142 print(const struct ip6t_ip6 *ip,
143       const struct ip6t_entry_target *target,
144       int numeric)
145 {
146         const struct ip6t_route_target_info *route_info
147                 = (const struct ip6t_route_target_info *)target->data;
148
149         printf("ROUTE ");
150
151         if (route_info->oif[0])
152                 printf("oif:%s ", route_info->oif);
153
154         if (route_info->gw[0] 
155             || route_info->gw[1] 
156             || route_info->gw[2] 
157             || route_info->gw[3]) {
158                 char address[INET6_ADDRSTRLEN];
159                 printf("gw:%s ", inet_ntop(AF_INET6, route_info->gw, address, INET6_ADDRSTRLEN));
160         }
161
162         if (route_info->flags & IP6T_ROUTE_CONTINUE)
163                 printf("continue");
164
165 }
166
167
168 static void save(const struct ip6t_ip6 *ip, 
169                  const struct ip6t_entry_target *target)
170 {
171         const struct ip6t_route_target_info *route_info
172                 = (const struct ip6t_route_target_info *)target->data;
173
174         if (route_info->oif[0])
175                 printf("--oif %s ", route_info->oif);
176
177         if (route_info->gw[0] 
178             || route_info->gw[1] 
179             || route_info->gw[2] 
180             || route_info->gw[3]) {
181                 char address[INET6_ADDRSTRLEN];
182                 printf("--gw %s ", inet_ntop(AF_INET6, route_info->gw, address, INET6_ADDRSTRLEN));
183         }
184
185         if (route_info->flags & IP6T_ROUTE_CONTINUE)
186                 printf("--continue ");
187 }
188
189
190 static
191 struct ip6tables_target route
192 = { NULL,
193     "ROUTE",
194     IPTABLES_VERSION,
195     IP6T_ALIGN(sizeof(struct ip6t_route_target_info)),
196     IP6T_ALIGN(sizeof(struct ip6t_route_target_info)),
197     &help,
198     &init,
199     &parse,
200     &final_check,
201     &print,
202     &save,
203     opts
204 };
205
206 void _init(void)
207 {
208         register_target6(&route);
209 }