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>
39 # define LOG(fmt, args...) cprintf(fmt, ##args);
41 # define LOG(fmt, args...) do { } while (0);
45 enum {L_FAIL
, L_ERROR
, L_UPGRADE
, L_ESTABLISHED
, L_SUCCESS
};
64 //struct iphdr ip; // size = 20
75 u_int8_t data
[1500 - 20];
79 static int read_interface(const char *interface
, int *ifindex
, unsigned char *mac
)
85 memset(&ifr
, 0, sizeof(struct ifreq
));
86 if ((fd
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
)) < 0) {
87 LOG("socket failed!: \n");
92 ifr
.ifr_addr
.sa_family
= AF_INET
;
93 strcpy(ifr
.ifr_name
, interface
);
95 if (ioctl(fd
, SIOCGIFINDEX
, &ifr
) == 0) {
96 *ifindex
= ifr
.ifr_ifindex
;
97 LOG("adapter index %d \n", ifr
.ifr_ifindex
);
99 if (ioctl(fd
, SIOCGIFHWADDR
, &ifr
) == 0) {
100 memcpy(mac
, ifr
.ifr_hwaddr
.sa_data
, 6);
101 LOG("adapter hardware address %02x:%02x:%02x:%02x:%02x:%02x \n", mac
[0], mac
[1], mac
[2], mac
[3], mac
[4], mac
[5]);
105 LOG("SIOCGIFHWADDR failed!\n");
109 LOG("SIOCGIFINDEX failed!\n");
115 static int raw_socket(int ifindex
)
118 struct sockaddr_ll sock
;
120 LOG("Opening raw socket on ifindex %d\n", ifindex
);
121 if ((fd
= socket(PF_PACKET
, SOCK_RAW
, htons(ETH_P_IP
))) < 0) {
122 LOG("socket call failed: \n");
126 sock
.sll_family
= AF_PACKET
;
127 sock
.sll_protocol
= htons(ETH_P_IP
);
128 sock
.sll_ifindex
= ifindex
;
129 if (bind(fd
, (struct sockaddr
*) &sock
, sizeof(sock
)) < 0) {
130 LOG("bind call failed: \n");
138 static u_int16_t
checksum(void *addr
, int count
)
140 // Compute Internet Checksum for "count" bytes beginning at location "addr".
141 register int32_t sum
= 0;
142 u_int16_t
*source
= (u_int16_t
*) addr
;
145 /* This is the inner loop */
150 /* Add left-over byte, if any */
152 /* Make sure that the left-over byte is added correctly both with little and big endian hosts */
154 *(unsigned char *)(&tmp
) = *(unsigned char *)source
;
158 /* Fold 32-bit sum to 16 bits */
160 sum
= (sum
& 0xffff) + (sum
>> 16);
164 static int listen_interface(char *interface
)
168 struct EthPacket packet
;
171 unsigned char mac
[6];
176 struct in_addr ipaddr
, netmask
;
179 if (read_interface(interface
, &ifindex
, mac
) < 0) {
183 fd
= raw_socket(ifindex
);
185 LOG("FATAL: couldn't listen on socket\n");
190 if (!wait_action_idle(5)) { // Don't execute during upgrading
203 LOG("Waitting for select... \n");
204 retval
= select(fd
+ 1, &rfds
, NULL
, NULL
, &tv
);
207 printf("no packet recieved! \n\n");
211 memset(&packet
, 0, sizeof(struct EthPacket
));
212 bytes
= read(fd
, &packet
, sizeof(struct EthPacket
));
215 LOG("couldn't read on raw listening socket -- ignoring\n");
216 usleep(500000); // possible down interface, looping condition
220 if (bytes
< (int) (sizeof(struct iphdr
))) {
221 LOG("message too short, ignoring\n");
226 if (memcmp(mac
, packet
.dst_mac
, 6) != 0) {
227 LOG("dest %02x:%02x:%02x:%02x:%02x:%02x mac not the router\n",
228 packet
.dst_mac
[0], packet
.dst_mac
[1], packet
.dst_mac
[2],
229 packet
.dst_mac
[3], packet
.dst_mac
[4], packet
.dst_mac
[5]);
234 if (inet_addr(nvram_safe_get("lan_ipaddr")) == *(u_int32_t
*)packet
.daddr
) {
235 LOG("dest ip equal to lan ipaddr\n");
240 LOG("inet_addr=%x, packet.daddr=%x",inet_addr(nvram_safe_get("lan_ipaddr")),*(u_int32_t
*)packet
.daddr
);
242 //for (i=0; i<34;i++) {
243 // if (i%16==0) printf("\n");
244 // printf("%02x ",*(((u_int8_t *)packet)+i));
248 LOG("%02X%02X%02X%02X%02X%02X,%02X%02X%02X%02X%02X%02X,%02X%02X\n",
249 packet
.dst_mac
[0], packet
.dst_mac
[1], packet
.dst_mac
[2],
250 packet
.dst_mac
[3], packet
.dst_mac
[4], packet
.dst_mac
[5],
251 packet
.src_mac
[0], packet
.src_mac
[1], packet
.src_mac
[2],
252 packet
.src_mac
[3], packet
.src_mac
[4], packet
.src_mac
[5],
253 packet
.type
[0],packet
.type
[1]);
255 LOG("ip.version = %x", packet
.version
);
256 LOG("ip.tos = %x", packet
.tos
);
257 LOG("ip.tot_len = %x", packet
.tot_len
);
258 LOG("ip.id = %x", packet
.id
);
259 LOG("ip.ttl= %x", packet
.ttl
);
260 LOG("ip.protocol= %x", packet
.protocol
);
261 LOG("ip.check=%04x", packet
.check
);
262 LOG("ip.saddr=%08x", *(u_int32_t
*)&(packet
.saddr
));
263 LOG("ip.daddr=%08x", *(u_int32_t
*)&(packet
.daddr
));
265 if (*(u_int16_t
*)packet
.type
== 0x0800) {
266 LOG("not ip protocol");
271 /* ignore any extra garbage bytes */
272 bytes
= ntohs(packet
.tot_len
);
274 /* check IP checksum */
275 check
= packet
.check
;
278 if (check
!= checksum(&(packet
.version
), sizeof(struct iphdr
))) {
279 LOG("bad IP header checksum, ignoring\n");
280 LOG("check received = %X, should be %X",check
, checksum(&(packet
.version
), sizeof(struct iphdr
)));
285 LOG("oooooh!!! got some!\n");
287 if (nvram_match("wan_proto", "pptp")) {
288 inet_aton(nvram_safe_get("pptp_server_ip"), &ipaddr
);
290 else if (nvram_match("wan_proto", "l2tp")) {
292 inet_aton(nvram_safe_get("lan_ipaddr"), &ipaddr
); // checkme: why? zzz
296 inet_aton(nvram_safe_get("wan_ipaddr"), &ipaddr
);
298 inet_aton(nvram_safe_get("wan_netmask"), &netmask
);
299 LOG("gateway=%08x", ipaddr
.s_addr
);
300 LOG("netmask=%08x", netmask
.s_addr
);
302 if ((ipaddr
.s_addr
& netmask
.s_addr
) != (*(u_int32_t
*)&(packet
.daddr
) & netmask
.s_addr
)) {
303 if (nvram_match("wan_proto", "l2tp")) {
319 int listen_main(int argc
, char *argv
[])
324 usage_exit(argv
[0], "<interface>");
328 printf("Starting listen on %s\n", interface
);
330 if (fork() != 0) return 0;
333 switch (listen_interface(interface
)) {
335 LOG("\n*** LAN to WAN packet received\n\n");
338 if (check_wanup()) return 0;
340 // Connect fail, we want to re-connect session
344 LOG("listen: nothing to do...\n");
347 LOG("The link had been established\n");