2 listen.c -- Listen for any packet through an interface
3 Copyright 2003, CyberTAN Inc. All Rights Reserved
5 This is UNPUBLISHED PROPRIETARY SOURCE CODE of CyberTAN Inc.
6 the contents of this file may not be disclosed to third parties,
7 copied or duplicated in any form without the prior written
8 permission of CyberTAN Inc.
10 This software should be used as a reference only, and it not
11 intended for production use!
13 THIS SOFTWARE IS OFFERED "AS IS", AND CYBERTAN GRANTS NO WARRANTIES OF ANY
14 KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. CYBERTAN
15 SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
16 FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE
21 #include <sys/ioctl.h>
22 #include <arpa/inet.h>
26 #if __GLIBC__ >=2 && __GLIBC_MINOR >= 1
27 #include <netpacket/packet.h>
28 #include <net/ethernet.h>
30 #include <asm/types.h>
31 #include <linux/if_packet.h>
32 #include <linux/if_ether.h>
37 enum {L_FAIL
, L_ERROR
, L_UPGRADE
, L_ESTABLISHED
, L_SUCCESS
};
50 } __attribute__((packed
));
56 //struct iphdr ip; // size = 20
67 u_int8_t data
[1500 - 20];
68 } __attribute__((packed
));
71 static int read_interface(const char *interface
, int *ifindex
, unsigned char *mac
)
77 memset(&ifr
, 0, sizeof(struct ifreq
));
78 if ((fd
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
)) < 0) {
79 LOG("socket failed!: \n");
84 ifr
.ifr_addr
.sa_family
= AF_INET
;
85 strcpy(ifr
.ifr_name
, interface
);
87 if (ioctl(fd
, SIOCGIFINDEX
, &ifr
) == 0) {
88 *ifindex
= ifr
.ifr_ifindex
;
89 LOG("adapter index %d \n", ifr
.ifr_ifindex
);
91 if (ioctl(fd
, SIOCGIFHWADDR
, &ifr
) == 0) {
92 memcpy(mac
, ifr
.ifr_hwaddr
.sa_data
, 6);
93 LOG("adapter hardware address %02x:%02x:%02x:%02x:%02x:%02x \n", mac
[0], mac
[1], mac
[2], mac
[3], mac
[4], mac
[5]);
97 LOG("SIOCGIFHWADDR failed!\n");
101 LOG("SIOCGIFINDEX failed!\n");
107 static int raw_socket(int ifindex
)
110 struct sockaddr_ll sock
;
112 LOG("Opening raw socket on ifindex %d\n", ifindex
);
113 if ((fd
= socket(PF_PACKET
, SOCK_RAW
, htons(ETH_P_IP
))) < 0) {
114 LOG("socket call failed: \n");
118 sock
.sll_family
= AF_PACKET
;
119 sock
.sll_protocol
= htons(ETH_P_IP
);
120 sock
.sll_ifindex
= ifindex
;
121 if (bind(fd
, (struct sockaddr
*) &sock
, sizeof(sock
)) < 0) {
122 LOG("bind call failed: \n");
130 static u_int16_t
checksum(void *addr
, int count
)
132 // Compute Internet Checksum for "count" bytes beginning at location "addr".
133 register int32_t sum
= 0;
134 u_int16_t
*source
= (u_int16_t
*) addr
;
137 /* This is the inner loop */
142 /* Add left-over byte, if any */
144 /* Make sure that the left-over byte is added correctly both with little and big endian hosts */
146 *(unsigned char *)(&tmp
) = *(unsigned char *)source
;
150 /* Fold 32-bit sum to 16 bits */
152 sum
= (sum
& 0xffff) + (sum
>> 16);
156 static int listen_interface(char *interface
, int wan_proto
)
160 struct EthPacket packet
;
163 unsigned char mac
[6];
168 struct in_addr ipaddr
, netmask
;
171 if (read_interface(interface
, &ifindex
, mac
) < 0) {
175 fd
= raw_socket(ifindex
);
177 LOG("FATAL: couldn't listen on socket\n");
182 if (!wait_action_idle(5)) { // Don't execute during upgrading
195 LOG("Waitting for select... \n");
196 retval
= select(fd
+ 1, &rfds
, NULL
, NULL
, &tv
);
199 printf("no packet recieved! \n\n");
203 memset(&packet
, 0, sizeof(struct EthPacket
));
204 bytes
= read(fd
, &packet
, sizeof(struct EthPacket
));
207 LOG("couldn't read on raw listening socket -- ignoring\n");
208 usleep(500000); // possible down interface, looping condition
212 if (bytes
< (int) (sizeof(struct iphdr
))) {
213 LOG("message too short, ignoring\n");
218 if (memcmp(mac
, packet
.dst_mac
, 6) != 0) {
219 LOG("dest %02x:%02x:%02x:%02x:%02x:%02x mac not the router\n",
220 packet
.dst_mac
[0], packet
.dst_mac
[1], packet
.dst_mac
[2],
221 packet
.dst_mac
[3], packet
.dst_mac
[4], packet
.dst_mac
[5]);
226 if (inet_addr(nvram_safe_get("lan_ipaddr")) == *(u_int32_t
*)packet
.daddr
) {
227 LOG("dest ip equal to lan ipaddr\n");
232 LOG("inet_addr=%x, packet.daddr=%x",inet_addr(nvram_safe_get("lan_ipaddr")),*(u_int32_t
*)packet
.daddr
);
234 //for (i=0; i<34;i++) {
235 // if (i%16==0) printf("\n");
236 // printf("%02x ",*(((u_int8_t *)packet)+i));
240 LOG("%02X%02X%02X%02X%02X%02X,%02X%02X%02X%02X%02X%02X,%02X%02X\n",
241 packet
.dst_mac
[0], packet
.dst_mac
[1], packet
.dst_mac
[2],
242 packet
.dst_mac
[3], packet
.dst_mac
[4], packet
.dst_mac
[5],
243 packet
.src_mac
[0], packet
.src_mac
[1], packet
.src_mac
[2],
244 packet
.src_mac
[3], packet
.src_mac
[4], packet
.src_mac
[5],
245 packet
.type
[0],packet
.type
[1]);
247 LOG("ip.version = %x", packet
.version
);
248 LOG("ip.tos = %x", packet
.tos
);
249 LOG("ip.tot_len = %x", packet
.tot_len
);
250 LOG("ip.id = %x", packet
.id
);
251 LOG("ip.ttl= %x", packet
.ttl
);
252 LOG("ip.protocol= %x", packet
.protocol
);
253 LOG("ip.check=%04x", packet
.check
);
254 LOG("ip.saddr=%08x", *(u_int32_t
*)&(packet
.saddr
));
255 LOG("ip.daddr=%08x", *(u_int32_t
*)&(packet
.daddr
));
257 if (*(u_int16_t
*)packet
.type
== 0x0800) {
258 LOG("not ip protocol");
263 /* ignore any extra garbage bytes */
264 bytes
= ntohs(packet
.tot_len
);
266 /* check IP checksum */
267 check
= packet
.check
;
270 if (check
!= checksum(&(packet
.version
), sizeof(struct iphdr
))) {
271 LOG("bad IP header checksum, ignoring\n");
272 LOG("check received = %X, should be %X",check
, checksum(&(packet
.version
), sizeof(struct iphdr
)));
277 LOG("oooooh!!! got some!\n");
281 inet_aton(nvram_safe_get("pptp_server_ip"), &ipaddr
);
285 inet_aton(nvram_safe_get("lan_ipaddr"), &ipaddr
); // checkme: why? zzz
289 inet_aton(nvram_safe_get("wan_ipaddr"), &ipaddr
);
292 inet_aton(nvram_safe_get("wan_netmask"), &netmask
);
293 LOG("gateway=%08x", ipaddr
.s_addr
);
294 LOG("netmask=%08x", netmask
.s_addr
);
296 if ((ipaddr
.s_addr
& netmask
.s_addr
) != (*(u_int32_t
*)&(packet
.daddr
) & netmask
.s_addr
)) {
297 if (wan_proto
== WP_L2TP
) {
313 int listen_main(int argc
, char *argv
[])
318 usage_exit(argv
[0], "<interface>");
322 printf("Starting listen on %s\n", interface
);
324 if (fork() != 0) return 0;
327 switch (listen_interface(interface
, get_wan_proto())) {
329 LOG("\n*** LAN to WAN packet received\n\n");
332 if (check_wanup()) return 0;
334 // Connect fail, we want to re-connect session
338 LOG("listen: nothing to do...\n");
341 LOG("The link had been established\n");