📄 if.c
字号:
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: Interface name too long"); } if (strlen(ifname) < 2) { rp_fatal("socket: Interface name too short"); } 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."); } /* Common error is to omit /dev/ */ if (errno == ENOENT) { char ifname[512]; snprintf(ifname, sizeof(ifname), "/dev/%s", base_dev); if ((fd = open(ifname, O_RDWR)) < 0) { if (errno == EPERM) { rp_fatal("Cannot create raw socket -- pppoe must be run as root."); } } } } if (fd < 0) { fatalSys("socket"); }/* rearranged order of DLPI code - delphys 20010803 */ dlattachreq(fd, ppa); dlokack(fd, (char *)buf); dlbindreq(fd, type, 0, DL_CLDLS, 0, 0); dlbindack(fd, (char *)buf); dlinforeq(fd); dlinfoack(fd, (char *)buf); dl_abssaplen = ABS(dlp->info_ack.dl_sap_length); dl_saplen = dlp->info_ack.dl_sap_length; if (ETHERADDRL != (dlp->info_ack.dl_addr_length - dl_abssaplen)) fatalSys("invalid destination physical address length"); dl_addrlen = dl_abssaplen + ETHERADDRL;/* ethernet address retrieved as part of DL_INFO_ACK - delphys 20010803 */ memcpy(hwaddr, (u_char*)((char*)(dlp) + (int)(dlp->info_ack.dl_addr_offset)), ETHERADDRL); if ( strioctl(fd, DLIOCRAW, -1, 0, NULL) < 0 ) { fatalSys("DLIOCRAW"); } if (ioctl(fd, I_FLUSH, FLUSHR) < 0) fatalSys("I_FLUSH"); return fd;}/* cloned from dlcommon.c */void dlpromisconreq(int fd, u_long level){ dl_promiscon_req_t promiscon_req; struct strbuf ctl; int flags; promiscon_req.dl_primitive = DL_PROMISCON_REQ; promiscon_req.dl_level = level; ctl.maxlen = 0; ctl.len = sizeof (promiscon_req); ctl.buf = (char *) &promiscon_req; flags = 0; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) fatalSys("dlpromiscon: putmsg");}void dlinforeq(int fd){ dl_info_req_t info_req; struct strbuf ctl; int flags; info_req.dl_primitive = DL_INFO_REQ; ctl.maxlen = 0; ctl.len = sizeof (info_req); ctl.buf = (char *) &info_req; flags = RS_HIPRI; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) fatalSys("dlinforeq: putmsg");}void dlunitdatareq(int fd, u_char *addrp, int addrlen, u_long minpri, u_long maxpri, u_char *datap, int datalen){ long buf[MAXDLBUF]; union DL_primitives *dlp; struct strbuf data, ctl; dlp = (union DL_primitives*) buf; dlp->unitdata_req.dl_primitive = DL_UNITDATA_REQ; dlp->unitdata_req.dl_dest_addr_length = addrlen; dlp->unitdata_req.dl_dest_addr_offset = sizeof (dl_unitdata_req_t); dlp->unitdata_req.dl_priority.dl_min = minpri; dlp->unitdata_req.dl_priority.dl_max = maxpri; (void) memcpy(OFFADDR(dlp, sizeof (dl_unitdata_req_t)), addrp, addrlen); ctl.maxlen = 0; ctl.len = sizeof (dl_unitdata_req_t) + addrlen; ctl.buf = (char *) buf; data.maxlen = 0; data.len = datalen; data.buf = (char *) datap; if (putmsg(fd, &ctl, &data, 0) < 0) fatalSys("dlunitdatareq: putmsg");}void dlinfoack(int fd, char *bufp){ union DL_primitives *dlp; struct strbuf ctl; int flags; ctl.maxlen = MAXDLBUF; ctl.len = 0; ctl.buf = bufp; strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlinfoack"); dlp = (union DL_primitives *) ctl.buf; expecting(DL_INFO_ACK, dlp); if (ctl.len < sizeof (dl_info_ack_t)) { char buffer[256]; sprintf(buffer, "dlinfoack: response ctl.len too short: %d", ctl.len); rp_fatal(buffer); } if (flags != RS_HIPRI) rp_fatal("dlinfoack: DL_INFO_ACK was not M_PCPROTO"); if (ctl.len < sizeof (dl_info_ack_t)) { char buffer[256]; sprintf(buffer, "dlinfoack: short response ctl.len: %d", ctl.len); rp_fatal(buffer); }}void dlbindreq(int fd, u_long sap, u_long max_conind, u_long service_mode, u_long conn_mgmt, u_long xidtest){ dl_bind_req_t bind_req; struct strbuf ctl; int flags; bind_req.dl_primitive = DL_BIND_REQ; bind_req.dl_sap = sap; bind_req.dl_max_conind = max_conind; bind_req.dl_service_mode = service_mode; bind_req.dl_conn_mgmt = conn_mgmt; bind_req.dl_xidtest_flg = xidtest; ctl.maxlen = 0; ctl.len = sizeof (bind_req); ctl.buf = (char *) &bind_req; flags = 0; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) fatalSys("dlbindreq: putmsg");}void dlattachreq(int fd, u_long ppa){ dl_attach_req_t attach_req; struct strbuf ctl; int flags; attach_req.dl_primitive = DL_ATTACH_REQ; attach_req.dl_ppa = ppa; ctl.maxlen = 0; ctl.len = sizeof (attach_req); ctl.buf = (char *) &attach_req; flags = 0; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) fatalSys("dlattachreq: putmsg");}void dlokack(int fd, char *bufp){ union DL_primitives *dlp; struct strbuf ctl; int flags; ctl.maxlen = MAXDLBUF; ctl.len = 0; ctl.buf = bufp; strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlokack"); dlp = (union DL_primitives *) ctl.buf; expecting(DL_OK_ACK, dlp); if (ctl.len < sizeof (dl_ok_ack_t)) { char buffer[256]; sprintf(buffer, "dlokack: response ctl.len too short: %d", ctl.len); rp_fatal(buffer); } if (flags != RS_HIPRI) rp_fatal("dlokack: DL_OK_ACK was not M_PCPROTO"); if (ctl.len < sizeof (dl_ok_ack_t)) { char buffer[256]; sprintf(buffer, "dlokack: short response ctl.len: %d", ctl.len); rp_fatal(buffer); }}void dlbindack(int fd, char *bufp){ union DL_primitives *dlp; struct strbuf ctl; int flags; ctl.maxlen = MAXDLBUF; ctl.len = 0; ctl.buf = bufp; strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlbindack"); dlp = (union DL_primitives *) ctl.buf; expecting(DL_BIND_ACK, dlp); if (flags != RS_HIPRI) rp_fatal("dlbindack: DL_OK_ACK was not M_PCPROTO"); if (ctl.len < sizeof (dl_bind_ack_t)) { char buffer[256]; sprintf(buffer, "dlbindack: short response ctl.len: %d", ctl.len); rp_fatal(buffer); }}int strioctl(int fd, int cmd, int timout, int len, char *dp){ struct strioctl sioc; int rc; sioc.ic_cmd = cmd; sioc.ic_timout = timout; sioc.ic_len = len; sioc.ic_dp = dp; rc = ioctl(fd, I_STR, &sioc); if (rc < 0) return (rc); else return (sioc.ic_len);}void strgetmsg(int fd, struct strbuf *ctlp, struct strbuf *datap, int *flagsp, char *caller){ int rc; static char errmsg[80]; /* * Start timer. */ (void) signal(SIGALRM, sigalrm); if (alarm(MAXWAIT) < 0) { (void) sprintf(errmsg, "%s: alarm", caller); fatalSys(errmsg); } /* * Set flags argument and issue getmsg(). */ *flagsp = 0; if ((rc = getmsg(fd, ctlp, datap, flagsp)) < 0) { (void) sprintf(errmsg, "%s: getmsg", caller); fatalSys(errmsg); } /* * Stop timer. */ if (alarm(0) < 0) { (void) sprintf(errmsg, "%s: alarm", caller); fatalSys(errmsg); } /* * Check for MOREDATA and/or MORECTL. */ if ((rc & (MORECTL | MOREDATA)) == (MORECTL | MOREDATA)) { char buffer[256]; sprintf(buffer, "%s: MORECTL|MOREDATA", caller); rp_fatal(buffer); } if (rc & MORECTL) { char buffer[256]; sprintf(buffer, "%s: MORECTL", caller); rp_fatal(buffer); } if (rc & MOREDATA) { char buffer[256]; sprintf(buffer, "%s: MOREDATA", caller); rp_fatal(buffer); } /* * Check for at least sizeof (long) control data portion. */ if (ctlp->len < sizeof (long)) { char buffer[256]; sprintf(buffer, "getmsg: control portion length < sizeof (long): %d", ctlp->len); rp_fatal(buffer); }}void sigalrm(int sig){ (void) rp_fatal("sigalrm: TIMEOUT");}void expecting(int prim, union DL_primitives *dlp){ if (dlp->dl_primitive != (u_long)prim) { char buffer[256]; sprintf(buffer, "expected %s got %s", dlprim(prim), dlprim(dlp->dl_primitive)); rp_fatal(buffer); exit(1); }}char *dlprim(u_long prim){ static char primbuf[80]; switch ((int)prim) { CASERET(DL_INFO_REQ); CASERET(DL_INFO_ACK); CASERET(DL_ATTACH_REQ); CASERET(DL_DETACH_REQ); CASERET(DL_BIND_REQ); CASERET(DL_BIND_ACK); CASERET(DL_UNBIND_REQ); CASERET(DL_OK_ACK); CASERET(DL_ERROR_ACK); CASERET(DL_SUBS_BIND_REQ); CASERET(DL_SUBS_BIND_ACK); CASERET(DL_UNITDATA_REQ); CASERET(DL_UNITDATA_IND); CASERET(DL_UDERROR_IND); CASERET(DL_UDQOS_REQ); CASERET(DL_CONNECT_REQ); CASERET(DL_CONNECT_IND); CASERET(DL_CONNECT_RES); CASERET(DL_CONNECT_CON); CASERET(DL_TOKEN_REQ); CASERET(DL_TOKEN_ACK); CASERET(DL_DISCONNECT_REQ); CASERET(DL_DISCONNECT_IND); CASERET(DL_RESET_REQ); CASERET(DL_RESET_IND); CASERET(DL_RESET_RES); CASERET(DL_RESET_CON); default: (void) sprintf(primbuf, "unknown primitive 0x%lx", prim); return (primbuf); }}#endif /* USE_DLPI */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -