3 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
30 #include <arpa/inet.h>
31 #include <sys/ioctl.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <net/if_arp.h>
35 #include <netinet/in.h>
36 #include <netinet/ip6.h> /* ip6_hdr */
37 #include <net/ethernet.h>
40 #define SNAP_LEN BUFSIZ
41 #define SIZE_ETHERNET 14 /* Ethernet headers are always exactly 14 bytes */
42 #define ETHERTYPE_IPV6 0xdd86
43 #define SIZE_IP6 40 /* IPv6 headers are always exactly 40 bytes */
45 /* MAC address structure */
46 typedef unsigned char s_mac_addr
[6];
48 /* Ethernet header structure */
50 s_mac_addr dest
; /* 48 b; destination host (MAC) address */
51 s_mac_addr src
; /* 48 b; source host (MAC) address */
52 unsigned short type
; /* 16 b; IP/ARP/RARP/... */
55 /* IPv6 header structure */
57 unsigned char ver
; /* 8 b; version */
58 unsigned char traffic_class
; /* 8 b; traffic class */
59 unsigned short flow_label
; /* 16 b; flow label (qos) */
60 unsigned short len
; /* 16 b; payload length */
61 unsigned char next_header
; /* 8 b; next header */
62 unsigned char hop_limit
; /* 8 b; hop limit (replaces ttl) */
63 struct in6_addr ip_src
; /* 128 b; source address */
64 struct in6_addr ip_dest
; /* 128 b; destination address */
68 struct in6_addr prefix
;
75 typedef struct ipv6_context
{
76 struct ipv6_context
*next
, *prev
;
83 unsigned ipv6_find (struct in6_addr
*addr
)
87 for (ipv6
= ipv6_list
.next
; ipv6
!= &ipv6_list
; ipv6
= ipv6
->next
) {
88 if (!memcmp (&ipv6
->addr
, addr
, sizeof (struct in6_addr
)))
95 unsigned ipv6_add (struct in6_addr
*addr
)
100 /* alloc and init context */
101 ipv6_t
*ipv6
= (ipv6_t
*) malloc (sizeof (ipv6_t
));
106 memcpy (&ipv6
->addr
, addr
, sizeof (struct in6_addr
));
109 ipv6
->next
= &ipv6_list
;
110 ipv6
->prev
= ipv6_list
.prev
;
111 ipv6
->prev
->next
= ipv6
;
112 ipv6
->next
->prev
= ipv6
;
115 char addr_src
[INET6_ADDRSTRLEN
];
116 inet_ntop (AF_INET6
, addr
, addr_src
, INET6_ADDRSTRLEN
);
119 printf ("> new ipv6: %s\n", addr_src
);
121 sprintf (str
, "ip -6 neigh add proxy %s dev eth0", addr_src
);
128 void handle_ipv6 (struct s_ethernet
*eth
, unsigned char *packet
)
130 /* define/compute IP header offset */
131 struct s_ip6
*ip
= (struct s_ip6
*) packet
;
133 /* DEBUG: print source and destination IP addresses */
135 char addr_src
[INET6_ADDRSTRLEN
];
136 char addr_dest
[INET6_ADDRSTRLEN
];
137 inet_ntop (AF_INET6
, &ip
->ip_src
, addr_src
, INET6_ADDRSTRLEN
);
138 inet_ntop (AF_INET6
, &ip
->ip_dest
, addr_dest
, INET6_ADDRSTRLEN
);
140 printf("> From: %s\n", addr_src
);
141 printf("> To: %s\n", addr_dest
);
143 if (!memcmp (&ip
->ip_src
, &config
.prefix
, config
.len
/8))
144 ipv6_add (&ip
->ip_src
);
147 void handle_packet (unsigned char *args
, const struct pcap_pkthdr
*header
, const unsigned char *packet
)
149 /* define ethernet header */
150 struct s_ethernet
*eth
= (struct s_ethernet
*) packet
;
151 unsigned char *payload
= (unsigned char *) (packet
);
153 /* it could be actually whatever packet, but we assume its tunnel interface */
154 return handle_ipv6 (eth
, payload
);
157 void daemonize (char *dev
)
164 int ipid
= getpid ();
166 /* detach if asked */
168 return; /* already a daemon */
170 /* fork to guarantee we are not process group leader */
174 exit (1); /* fork error */
176 exit (0); /* parent exits */
178 /* child (daemon) continues */
179 setsid (); /* obtain a new process group */
182 printf ("> started with pid -> %d\n", ipid
);
183 /* fork again so we become process group leader
184 * and cannot regain a controlling tty
189 exit (1); /* fork error */
191 exit (0); /* parent exits */
194 for (i
= getdtablesize (); i
>= 0; --i
)
195 close (i
); /* close all descriptors */
197 /* close parent fds and send output to fds 0, 1 and 2 to bitbucket */
198 i
= open ("/dev/null", O_RDWR
);
204 dup (i
); /* handle standart I/O */
206 sprintf (spid
, "%s.pid", dev
);
208 /* create local lock */
209 lockfd
= open (spid
, O_RDWR
| O_CREAT
, 0640);
212 perror ("lock: open");
217 if (lockf (lockfd
, F_TLOCK
, 0) < 0) {
218 perror ("lock: lockf");
219 printf ("> ndprouter is already running.\n");
226 lock
.l_type
= F_RDLCK
;
228 lock
.l_whence
= SEEK_SET
;
231 if (fcntl (lockfd
, F_SETLK
, &lock
) < 0) {
232 printf ("> ndprouter is already running.\n");
237 /* write to pid to lockfile */
238 snprintf (pid
, 16, "%d\n", getpid ());
239 write (lockfd
, pid
, strlen (pid
));
241 /* restrict created files to 0750 */
246 int main (int argc
, char **argv
)
248 char errbuf
[PCAP_ERRBUF_SIZE
]; /* error buffer */
250 if (argc
!= 3 && argc
!= 4) {
251 printf ("syntax: <interface> <prefix/len> [-d]\n");
255 char *dev
= argv
[1]; /* captured device */
256 char *prefix
= argv
[2];
259 if (argv
[3][0] == '-' && argv
[3][1] == 'd')
266 for (i
= 0; prefix
[i
]; i
++) {
267 if (prefix
[i
] == '/') {
275 printf ("ERROR -> Prefix length must be specified, example: 2001:abc:def::/64\n");
279 char *plen
= prefix
+ len
+ 1;
281 config
.len
= atoi (plen
);
283 if (config
.len
< 16 || config
.len
> 128) {
284 printf ("ERROR -> Prefix length is wrong length: 16-128 are allowed");
288 inet_pton (AF_INET6
, prefix
, &config
.prefix
);
290 ipv6_list
.next
= &ipv6_list
;
291 ipv6_list
.prev
= &ipv6_list
;
293 if (!config
.daemon
) {
296 /* print capture info */
297 printf ("> interface: %s\n", dev
);
298 printf ("> ipv6 prefix: %s/%d\n", prefix
, config
.len
);
302 /* open capture device */
303 pcap_t
*handle
= pcap_open_live (dev
, SNAP_LEN
, 1, 1, errbuf
);
306 fprintf (stderr
, "ERROR -> Couldn't open device %s: %s\n", dev
, errbuf
);
310 /* now we can set our callback function */
311 pcap_loop (handle
, 0, handle_packet
, NULL
);
313 /* free memory of pcap */