以太网wan与lan 自适应功能

张开发
2026/4/18 3:06:31 15 分钟阅读

分享文章

以太网wan与lan 自适应功能
路由器系统自动适别以太网口是WAN或LAN口的功能,这方便用户安装路由器的网络搭建。一、其原理:路由器设备接入网口时,系统判断是WAN口还是LAN口,主要根据是接入网线后,系统如何判断接入网口的上一级是否存在DHCP服务或PPPOE服务。如何存在则认为是WAN接入,否则为LAN接入。二、检测DHCP服务或PPPOE服务检测DHCP服务原理,路由器首先把接入的网口从桥中独立出来,要不然,不能从此网口发送数据进行检测工作。根据DHCP的原理,dhcp客户端发送discover包时,如果对端存在服务则返回offer数据包。因此,在接入网口发送discover包后,进行接收数据,看能否收到offer包即可确认是否为WAN口。检测PPPOE服务原理,同样路由器首先把接入的网口从桥中独立出来,并根据PPPOE协议原理,发送PADI包,然后进行接收是否存在PADO包,即可确认是否为WAN口。三、相应的实现源码如下:1、源码文件名如下netscan.c scan_common.c scan_common.h scan_dhcp.c scan_dhcp.h scan_pppoe.c scan_pppoe.h2、各文件源码cat netscan.c#include stdio.h#include unistd.h#include stdlib.h#include "scan_pppoe.h"#include "scan_dhcp.h"int main(int argc, char* argv[]){ char *iface; iface = (char *)malloc(sizeof(char)); iface = argv[1]; unsigned int time = 0; int message = 0; int result = 0; message = scan_pppoe_result(iface, time); if(message 0){ result = result + 1; } message = scan_dhcp_result(iface, time); if(message 0){ result = result + 1; } if(result 0 ){ char cmd[128]; sprintf(cmd,"echo '%s' /tmp/dhcp_iface",iface); system(cmd); }}cat scan_common.c/** Copyright (C) 2017 Konstantin Vasin** Licensed under GPLv2, see file LICENSE for more information.*/#include "scan_common.h"/* Endianness check */#define IS_BIG_ENDIAN (*(uint16_t *)"\0\xff" 0x100)/*** Get MAC address of interface.** @param ifname Interface name.* @param addr Array for MAC address.** @return -1 on failure, 0 on success.*/int s_get_hw_address(const char *ifname, uint8_t addr[ETH_ALEN]){ /* Copy interface name into ifreq */ struct ifreq ifr; memset(ifr, 0, sizeof(struct ifreq)); size_t if_name_len = strlen(ifname); if (if_name_len sizeof(ifr.ifr_name)) { memcpy(ifr.ifr_name, ifname, if_name_len); ifr.ifr_name[if_name_len] = 0; } else { return -1; } /* Create socket */ int fd = socket(AF_UNIX, SOCK_DGRAM, 0); if (fd 0) { return -1; } /* Get hw address */ if (ioctl(fd, SIOCGIFHWADDR, ifr) 0) { close (fd); return -1; } close(fd); memcpy (addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); return 0;}/*** Get Interface index.** @param ifname Interface name.** @return Interface index on success, zero on failure.*/unsigned int s_get_ifindex(const char *ifname){ /* Copy interface name into ifreq */ struct ifreq ifr; memset(ifr, 0, sizeof(struct ifreq)); size_t if_name_len = strlen(ifname); if (if_name_len sizeof(ifr.ifr_name)) { memcpy(ifr.ifr_name, ifname, if_name_len); ifr.ifr_name[if_name_len] = 0; } else { return -1; } /* Create socket */ int fd = socket(AF_UNIX, SOCK_DGRAM, 0); if (fd 0) { return 0; } /* Get interface index */ if (ioctl(fd, SIOCGIFINDEX, ifr) 0) { close (fd); return 0; } close(fd); return ifr.ifr_ifindex;}/*** Calculate internet checksum.** @param addr Start address.* @param nleft Length in bytes.** @return Checksum.*/uint16_t s_inet_cksum(uint16_t *addr, int nleft){ /* * Algorithm is simple, using a 32 bit accumulator, * we add sequential 16 bit words to it, and at the end, fold * back all the carry bits from the top 16 bits into the lower * 16 bits. */ unsigned sum = 0; while (nleft 1) { sum += *addr++; nleft -= 2; } /* Mop up an odd byte, if necessary */ if (nleft == 1) { if (IS_BIG_ENDIAN) sum += *(uint8_t *)addr 8; else sum += *(uint8_t *)addr; } /* Add back carry outs from top 16 bits to low 16 bits */ sum = (sum 16) + (sum 0xffff); /* add hi 16 to low 16 */ sum += (sum 16); /* add carry */ return (uint16_t)~sum;}/*** Calculate random id (unsigned 32-bit value).** @param Void.* @return id*/uint32_t s_random_id(void){ srand(time(NULL)); return rand();}/*** Add error value in result.** @param JSON object.* @param msg Error message** @return 0 on success, -1 on failure.*/int s_set_err(json_t *result, const char *msg, ...){ va_list ap; char buf[MAX_ERROR_LENGTH]; int ret = -1; va_start(ap, msg); if (msg != NULL) ret = vsnprintf(buf, sizeof(buf), msg, ap); va_end(ap); if (ret 0) ret = json_object_set_new_nocheck(result, "error", json_string(buf)); else ret = -1; return ret;}cat scan_common.h/** Copyright (C) 2017 Konstantin Vasin** Licensed under GPLv2, see file LICENSE for more information.*/#ifndef _SCAN_COMMON_H#define _SCAN_COMMON_H#include jansson.h#include errno.h#include unistd.h#include stdio.h#include stdlib.h#include stddef.h#include time.h#include string.h#include signal.h#include sys/ioctl.h#include arpa/inet.h#include linux/if_packet.h#include netinet/if_ether.h#include netinet/ip.h#include linux/udp.h#include net/if.h#include linux/sockios.h#include linux/filter.h//#include json-c/json.h#define MAX_WAIT_TIME 15#define MAX_ERROR_LENGTH 1500uint32_t s_random_id(void);int s_get_hw_address(const char *ifname, uint8_t addr[ETH_ALEN]);unsigned int s_get_ifindex(const char *ifname);uint16_t s_inet_cksum(uint16_t *addr, int nleft);int s_set_err(json_t *result, const char *msg, ...);#endif /* _SCAN_COMMON_H */cat scan_dhcp.c/** Copyright (C) 2017 Konstantin Vasin** Licensed under GPLv2, see file LICENSE for more information.*/#include "scan_common.h"#include "scan_dhcp.h"/* DHCP protocol. RFC 2131, RFC 2132 */#define DHCP_MAGIC 0x63825363#define DHCP_FIXED_LEN 240 /* with DHCP magic */#define DHCP_UDP_OVERHEAD 28 /* IP + UDP headers */#define DHCP_MTU_MAX 1500#define DHCP_MTU_MIN 576#define DHCP_OPTIONS_BUF_MIN (DHCP_MTU_MIN - DHCP_FIXED_LEN - DHCP_UDP_OVERHEAD)#define DHCP_OPTIONS_BUF_MAX (DHCP_MTU_MAX - DHCP_FIXED_LEN - DHCP_UDP_OVERHEAD)#define BOOTREQUEST 1#define BOOTREPLY 2/* DHCP Ports and Addresses */#define CLIENT_PORT 68#define SERVER_PORT 67/* DHCP packet */struct dhcp_packet { uint8_t op; /* BOOTREQUEST or BOOTREPLY */ uint8_t htype; /* hardware address type. 1 = 10Mb ethernet */ uint8_t hlen; /* hardware address length */ uint8_t hops; /* used by relay agents only */ uint32_t xid; /* unuque id */ uint16_t secs; /* seconds since client started looking */ uint16_t flags; /* only one flag */ uint32_t ciaddr; /* clients IP address (if already in use) */ uint32_t yiaddr; /* client IP address */ uint32_t siaddr_nip; /* next server used in bootstrap */ uint32_t gateway_nip; /* relay agent IP address */ uint8_t chaddr[16]; /* MAC address of client */ uint8_t sname[64]; /* server host name (ASCIZ) */ uint8_t file[128]; nbs

更多文章