📄 if.c
字号:
sprintf(buffer, "Unsupported BPF version: %d.%d (kernel: %d.%d)", BPF_MAJOR_VERSION, BPF_MINOR_VERSION, bpf_ver.bv_major, bpf_ver.bv_minor); rp_fatal(buffer); } /* allocate a receive packet buffer */ if (ioctl(fd, BIOCGBLEN, &bpfLength) < 0) { fatalSys("ioctl(BIOCGBLEN)"); } if (!(bpfBuffer = (unsigned char *) malloc(bpfLength))) { rp_fatal("malloc"); } /* reads should return as soon as there is a packet available */ optval = 1; if (ioctl(fd, BIOCIMMEDIATE, &optval) < 0) { fatalSys("ioctl(BIOCIMMEDIATE)"); } /* Bind the interface to the filter */ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); if (ioctl(fd, BIOCSETIF, &ifr) < 0) { char buffer[256]; sprintf(buffer, "ioctl(BIOCSETIF) can't select interface %.16s", ifname); rp_fatal(buffer); } syslog(LOG_INFO, "Interface=%.16s HWaddr=%02X:%02X:%02X:%02X:%02X:%02X Device=%.32s Buffer size=%d", ifname, hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5], bpfName, bpfLength); return fd;}#endif /* USE_BPF */#ifdef USE_LINUX_PACKET/***********************************************************************%FUNCTION: openInterface*%ARGUMENTS:* ifname -- name of interface* type -- Ethernet frame type* hwaddr -- if non-NULL, set to the hardware address*%RETURNS:* A raw socket for talking to the Ethernet card. Exits on error.*%DESCRIPTION:* Opens a raw Ethernet socket***********************************************************************/intopenInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr){ int optval=1; int fd; struct ifreq ifr; int domain, stype;#ifdef HAVE_STRUCT_SOCKADDR_LL struct sockaddr_ll sa;#else struct sockaddr sa;#endif memset(&sa, 0, sizeof(sa));#ifdef HAVE_STRUCT_SOCKADDR_LL domain = PF_PACKET; stype = SOCK_RAW;#else domain = PF_INET; stype = SOCK_PACKET;#endif if ((fd = socket(domain, stype, htons(type))) < 0) { /* Give a more helpful message for the common error case */ if (errno == EPERM) { rp_fatal("Cannot create raw socket -- pppoe must be run as root."); } fatalSys("socket"); } if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) < 0) { fatalSys("setsockopt"); } /* Fill in hardware address */ if (hwaddr) { strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { fatalSys("ioctl(SIOCGIFHWADDR)"); } memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);#ifdef ARPHRD_ETHER if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { char buffer[256]; sprintf(buffer, "Interface %.16s is not Ethernet", ifname); rp_fatal(buffer); }#endif if (NOT_UNICAST(hwaddr)) { char buffer[256]; sprintf(buffer, "Interface %.16s has broadcast/multicast MAC address??", ifname); rp_fatal(buffer); } } /* Sanity check on MTU */ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFMTU, &ifr) < 0) { fatalSys("ioctl(SIOCGIFMTU)"); } if (ifr.ifr_mtu < ETH_DATA_LEN) { char buffer[256]; sprintf(buffer, "Interface %.16s has MTU of %d -- should be %d. You may have serious connection problems.", ifname, ifr.ifr_mtu, ETH_DATA_LEN); printErr(buffer); }#ifdef HAVE_STRUCT_SOCKADDR_LL /* Get interface index */ sa.sll_family = AF_PACKET; sa.sll_protocol = htons(type); strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) { fatalSys("ioctl(SIOCFIGINDEX): Could not get interface index"); } sa.sll_ifindex = ifr.ifr_ifindex;#else strcpy(sa.sa_data, ifname);#endif /* We're only interested in packets on specified interface */ if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { fatalSys("bind"); } return fd;}#endif /* USE_LINUX *//************************************************************************%FUNCTION: sendPacket*%ARGUMENTS:* sock -- socket to send to* pkt -- the packet to transmit* size -- size of packet (in bytes)*%RETURNS:* 0 on success; -1 on failure*%DESCRIPTION:* Transmits a packet***********************************************************************/intsendPacket(PPPoEConnection *conn, int sock, PPPoEPacket *pkt, int size){#if defined(USE_BPF) if (write(sock, pkt, size) < 0) { sysErr("write (sendPacket)"); return -1; }#elif defined(HAVE_STRUCT_SOCKADDR_LL) if (send(sock, pkt, size, 0) < 0) { sysErr("send (sendPacket)"); return -1; }#else#ifdef USE_DLPI#define ABS(x) ((x) < 0 ? -(x) : (x)) u_char addr[MAXDLADDR]; u_char phys[MAXDLADDR]; u_char sap[MAXDLADDR]; u_char xmitbuf[MAXDLBUF]; int data_size; short tmp_sap; tmp_sap = htons(pkt->ethHdr.h_proto); data_size = size - sizeof(struct ethhdr); memcpy((char *)phys, (char *)pkt->ethHdr.h_dest, ETHERADDRL); memcpy((char *)sap, (char *)&tmp_sap, sizeof(ushort_t)); memcpy((char *)xmitbuf, (char *)pkt + sizeof(struct ethhdr), data_size); if (dl_saplen > 0) { /* order is sap+phys */ (void) memcpy((char*)addr, (char*)&sap, dl_abssaplen); (void) memcpy((char*)addr+dl_abssaplen, (char*)phys, ETHERADDRL); } else { /* order is phys+sap */ (void) memcpy((char*)addr, (char*)phys, ETHERADDRL); (void) memcpy((char*)addr+ETHERADDRL, (char*)&sap, dl_abssaplen); }#ifdef DL_DEBUG printf("%02x:%02x:%02x:%02x:%02x:%02x %02x:%02x\n", addr[0],addr[1],addr[2],addr[3],addr[4],addr[5], addr[6],addr[7]);#endif dlunitdatareq(sock, addr, dl_addrlen, 0, 0, xmitbuf, data_size);#else struct sockaddr sa; if (!conn) { rp_fatal("relay and server not supported on Linux 2.0 kernels"); } strcpy(sa.sa_data, conn->ifName); if (sendto(sock, pkt, size, 0, &sa, sizeof(sa)) < 0) { sysErr("sendto (sendPacket)"); return -1; }#endif#endif return 0;}#ifdef USE_BPF/************************************************************************%FUNCTION: clearPacketHeader*%ARGUMENTS:* pkt -- packet that needs its head clearing*%RETURNS:* nothing*%DESCRIPTION:* Clears a PPPoE packet header after a truncated packet has been* received. Insures that the packet will fail any integrity tests* and will be discarded by upper level routines. Also resets the* bpfSize and bpfOffset variables to force a new read on the next* call to receivePacket().***********************************************************************/voidclearPacketHeader(PPPoEPacket *pkt){ bpfSize = bpfOffset = 0; memset(pkt, 0, HDR_SIZE);}#endif/************************************************************************%FUNCTION: receivePacket*%ARGUMENTS:* sock -- socket to read from* pkt -- place to store the received packet* size -- set to size of packet in bytes*%RETURNS:* >= 0 if all OK; < 0 if error*%DESCRIPTION:* Receives a packet***********************************************************************/intreceivePacket(int sock, PPPoEPacket *pkt, int *size){#ifdef USE_BPF struct bpf_hdr hdr; int seglen, copylen; if (bpfSize <= 0) { bpfOffset = 0; if ((bpfSize = read(sock, bpfBuffer, bpfLength)) < 0) { sysErr("read (receivePacket)"); return -1; } } if (bpfSize < sizeof(hdr)) { syslog(LOG_ERR, "Truncated bpf packet header: len=%d", bpfSize); clearPacketHeader(pkt); /* resets bpfSize and bpfOffset */ return 0; } memcpy(&hdr, bpfBuffer + bpfOffset, sizeof(hdr)); if (hdr.bh_caplen != hdr.bh_datalen) { syslog(LOG_ERR, "Truncated bpf packet: caplen=%d, datalen=%d", hdr.bh_caplen, hdr.bh_datalen); clearPacketHeader(pkt); /* resets bpfSize and bpfOffset */ return 0; } seglen = hdr.bh_hdrlen + hdr.bh_caplen; if (seglen > bpfSize) { syslog(LOG_ERR, "Truncated bpf packet: seglen=%d, bpfSize=%d", seglen, bpfSize); clearPacketHeader(pkt); /* resets bpfSize and bpfOffset */ return 0; } seglen = BPF_WORDALIGN(seglen); *size = copylen = ((hdr.bh_caplen < sizeof(PPPoEPacket)) ? hdr.bh_caplen : sizeof(PPPoEPacket)); memcpy(pkt, bpfBuffer + bpfOffset + hdr.bh_hdrlen, copylen); if (seglen >= bpfSize) { bpfSize = bpfOffset = 0; } else { bpfSize -= seglen; bpfOffset += seglen; }#else#ifdef USE_DLPI struct strbuf data; int flags = 0; int retval; data.buf = (char *) pkt; data.maxlen = MAXDLBUF; data.len = 0; if ((retval = getmsg(sock, NULL, &data, &flags)) < 0) { sysErr("read (receivePacket)"); return -1; } *size = data.len; #else if ((*size = recv(sock, pkt, sizeof(PPPoEPacket), 0)) < 0) { sysErr("recv (receivePacket)"); return -1; }#endif#endif return 0;}#ifdef USE_DLPI/***********************************************************************%FUNCTION: openInterface*%ARGUMENTS:* ifname -- name of interface* type -- Ethernet frame type* hwaddr -- if non-NULL, set to the hardware address*%RETURNS:* A raw socket for talking to the Ethernet card. Exits on error.*%DESCRIPTION:* Opens a raw Ethernet socket***********************************************************************/intopenInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr){ int fd; long buf[MAXDLBUF]; union DL_primitives *dlp; char base_dev[PATH_MAX]; int ppa; if(strlen(ifname) > PATH_MAX) { rp_fatal("socket: string to long"); } ppa = atoi(&ifname[strlen(ifname)-1]); strncpy(base_dev, ifname, PATH_MAX); base_dev[strlen(base_dev)-1] = '\0'; /* rearranged order of DLPI code - delphys 20010803 */ dlp = (union DL_primitives*) buf; if (( fd = open(base_dev, O_RDWR)) < 0) { /* Give a more helpful message for the common error case */ if (errno == EPERM) { rp_fatal("Cannot create raw socket -- pppoe must be run as root.");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -