📄 pppoe-server.c
字号:
/* Ignore PADO and PADS totally */ break; default: /* Syslog an error */ break; }}/***********************************************************************%FUNCTION: sendErrorPADS*%ARGUMENTS:* sock -- socket to write to* source -- source Ethernet address* dest -- destination Ethernet address* errorTag -- error tag* errorMsg -- error message*%RETURNS:* Nothing*%DESCRIPTION:* Sends a PADS packet with an error message***********************************************************************/voidsendErrorPADS(int sock, unsigned char *source, unsigned char *dest, int errorTag, char *errorMsg){ PPPoEPacket pads; unsigned char *cursor = pads.payload; UINT16_t plen; PPPoETag err; int elen = strlen(errorMsg); memcpy(pads.ethHdr.h_dest, dest, ETH_ALEN); memcpy(pads.ethHdr.h_source, source, ETH_ALEN); pads.ethHdr.h_proto = htons(Eth_PPPOE_Discovery); pads.ver = 1; pads.type = 1; pads.code = CODE_PADS; pads.session = htons(0); plen = 0; err.type = htons(errorTag); err.length = htons(elen); memcpy(err.payload, errorMsg, elen); memcpy(cursor, &err, TAG_HDR_SIZE+elen); cursor += TAG_HDR_SIZE + elen; plen += TAG_HDR_SIZE + elen; if (relayId.type) { memcpy(cursor, &relayId, ntohs(relayId.length) + TAG_HDR_SIZE); cursor += ntohs(relayId.length) + TAG_HDR_SIZE; plen += ntohs(relayId.length) + TAG_HDR_SIZE; } if (hostUniq.type) { memcpy(cursor, &hostUniq, ntohs(hostUniq.length) + TAG_HDR_SIZE); cursor += ntohs(hostUniq.length) + TAG_HDR_SIZE; plen += ntohs(hostUniq.length) + TAG_HDR_SIZE; } pads.length = htons(plen); sendPacket(NULL, sock, &pads, (int) (plen + HDR_SIZE));}/***********************************************************************%FUNCTION: startPPPDUserMode*%ARGUMENTS:* session -- client session record*%RETURNS:* Nothing*%DESCRIPTION:* Starts PPPD for user-mode PPPoE***********************************************************************/voidstartPPPDUserMode(ClientSession *session){ /* Leave some room */ char *argv[32]; char buffer[SMALLBUF]; int c = 0; argv[c++] = "pppd"; argv[c++] = "pty"; /* Let's hope service-name does not have ' in it... */ snprintf(buffer, SMALLBUF, "%s -n -I %s -e %d:%02x:%02x:%02x:%02x:%02x:%02x%s -S '%s'", PPPOE_PATH, session->ethif->name, ntohs(session->sess), session->eth[0], session->eth[1], session->eth[2], session->eth[3], session->eth[4], session->eth[5], PppoeOptions, session->serviceName); argv[c++] = strdup(buffer); if (!argv[c-1]) { /* TODO: Send a PADT */ exit(EXIT_FAILURE); } argv[c++] = "file"; argv[c++] = PPPOE_SERVER_OPTIONS; snprintf(buffer, SMALLBUF, "%d.%d.%d.%d:%d.%d.%d.%d", (int) session->myip[0], (int) session->myip[1], (int) session->myip[2], (int) session->myip[3], (int) session->peerip[0], (int) session->peerip[1], (int) session->peerip[2], (int) session->peerip[3]); syslog(LOG_INFO, "Session %d created for client %02x:%02x:%02x:%02x:%02x:%02x (%d.%d.%d.%d) on %s using Service-Name '%s'", ntohs(session->sess), session->eth[0], session->eth[1], session->eth[2], session->eth[3], session->eth[4], session->eth[5], (int) session->peerip[0], (int) session->peerip[1], (int) session->peerip[2], (int) session->peerip[3], session->ethif->name, session->serviceName); argv[c++] = strdup(buffer); if (!argv[c-1]) { /* TODO: Send a PADT */ exit(EXIT_FAILURE); } argv[c++] = "nodetach"; argv[c++] = "noaccomp"; argv[c++] = "nobsdcomp"; argv[c++] = "nodeflate"; argv[c++] = "nopcomp"; argv[c++] = "novj"; argv[c++] = "novjccomp"; argv[c++] = "default-asyncmap"; if (Synchronous) { argv[c++] = "sync"; } if (PassUnitOptionToPPPD) { argv[c++] = "unit"; sprintf(buffer, "%d", ntohs(session->sess) - 1 - SessOffset); argv[c++] = buffer; } argv[c++] = NULL; execv(PPPD_PATH, argv); exit(EXIT_FAILURE);}/***********************************************************************%FUNCTION: startPPPDLinuxKernelMode*%ARGUMENTS:* session -- client session record*%RETURNS:* Nothing*%DESCRIPTION:* Starts PPPD for kernel-mode PPPoE on Linux***********************************************************************/voidstartPPPDLinuxKernelMode(ClientSession *session){ /* Leave some room */ char *argv[32]; int c = 0; char buffer[SMALLBUF]; argv[c++] = "pppd"; argv[c++] = "plugin"; argv[c++] = PLUGIN_PATH; argv[c++] = session->ethif->name; snprintf(buffer, SMALLBUF, "%d:%02x:%02x:%02x:%02x:%02x:%02x", ntohs(session->sess), session->eth[0], session->eth[1], session->eth[2], session->eth[3], session->eth[4], session->eth[5]); argv[c++] = "rp_pppoe_sess"; argv[c++] = strdup(buffer); if (!argv[c-1]) { /* TODO: Send a PADT */ exit(EXIT_FAILURE); } argv[c++] = "rp_pppoe_service"; argv[c++] = (char *) session->serviceName; argv[c++] = "file"; argv[c++] = PPPOE_SERVER_OPTIONS; snprintf(buffer, SMALLBUF, "%d.%d.%d.%d:%d.%d.%d.%d", (int) session->myip[0], (int) session->myip[1], (int) session->myip[2], (int) session->myip[3], (int) session->peerip[0], (int) session->peerip[1], (int) session->peerip[2], (int) session->peerip[3]); syslog(LOG_INFO, "Session %d created for client %02x:%02x:%02x:%02x:%02x:%02x (%d.%d.%d.%d) on %s using Service-Name '%s'", ntohs(session->sess), session->eth[0], session->eth[1], session->eth[2], session->eth[3], session->eth[4], session->eth[5], (int) session->peerip[0], (int) session->peerip[1], (int) session->peerip[2], (int) session->peerip[3], session->ethif->name, session->serviceName); argv[c++] = strdup(buffer); if (!argv[c-1]) { /* TODO: Send a PADT */ exit(EXIT_FAILURE); } argv[c++] = "nodetach"; argv[c++] = "noaccomp"; argv[c++] = "nobsdcomp"; argv[c++] = "nodeflate"; argv[c++] = "nopcomp"; argv[c++] = "novj"; argv[c++] = "novjccomp"; argv[c++] = "default-asyncmap"; if (PassUnitOptionToPPPD) { argv[c++] = "unit"; sprintf(buffer, "%d", ntohs(session->sess) - 1 - SessOffset); argv[c++] = buffer; } argv[c++] = NULL; execv(PPPD_PATH, argv); exit(EXIT_FAILURE);}/***********************************************************************%FUNCTION: startPPPD*%ARGUMENTS:* session -- client session record*%RETURNS:* Nothing*%DESCRIPTION:* Starts PPPD***********************************************************************/voidstartPPPD(ClientSession *session){ if (UseLinuxKernelModePPPoE) startPPPDLinuxKernelMode(session); else startPPPDUserMode(session);}/*********************************************************************** %FUNCTION: InterfaceHandler* %ARGUMENTS:* es -- event selector (ignored)* fd -- file descriptor which is readable* flags -- ignored* data -- Pointer to the Interface structure* %RETURNS:* Nothing* %DESCRIPTION:* Handles a packet ready at an interface***********************************************************************/voidInterfaceHandler(EventSelector *es, int fd, unsigned int flags, void *data){ serverProcessPacket((Interface *) data);}/*********************************************************************** %FUNCTION: PppoeStopSession* %ARGUMENTS:* ses -- the session* reason -- reason session is being stopped.* %RETURNS:* Nothing* %DESCRIPTION:* Kills pppd.***********************************************************************/static voidPppoeStopSession(ClientSession *ses, char const *reason){ /* Temporary structure for sending PADT's. */ PPPoEConnection conn; memset(&conn, 0, sizeof(conn)); conn.useHostUniq = 0; memcpy(conn.myEth, ses->ethif->mac, ETH_ALEN); conn.discoverySocket = ses->ethif->sock; conn.session = ses->sess; memcpy(conn.peerEth, ses->eth, ETH_ALEN); sendPADT(&conn, reason); ses->flags |= FLAG_SENT_PADT; if (ses->pid) { kill(ses->pid, SIGTERM); } ses->funcs = &DefaultSessionFunctionTable;}/*********************************************************************** %FUNCTION: PppoeSessionIsActive* %ARGUMENTS:* ses -- the session* %RETURNS:* True if session is active, false if not.***********************************************************************/static intPppoeSessionIsActive(ClientSession *ses){ return (ses->pid != 0);}#ifdef HAVE_LICENSE/*********************************************************************** %FUNCTION: getFreeMem* %ARGUMENTS:* None* %RETURNS:* The amount of free RAM in kilobytes, or -1 if it could not be* determined* %DESCRIPTION:* Reads Linux-specific /proc/meminfo file and extracts free RAM***********************************************************************/intgetFreeMem(void){ char buf[512]; int memfree=0, buffers=0, cached=0; FILE *fp = fopen("/proc/meminfo", "r"); if (!fp) return -1; while (fgets(buf, sizeof(buf), fp)) { if (!strncmp(buf, "MemFree:", 8)) { if (sscanf(buf, "MemFree: %d", &memfree) != 1) { fclose(fp); return -1; } } else if (!strncmp(buf, "Buffers:", 8)) { if (sscanf(buf, "Buffers: %d", &buffers) != 1) { fclose(fp); return -1; } } else if (!strncmp(buf, "Cached:", 7)) { if (sscanf(buf, "Cached: %d", &cached) != 1) { fclose(fp); return -1; } } } fclose(fp); /* return memfree + buffers + cached; */ return memfree;}#endif/*********************************************************************** %FUNCTION: pppoe_alloc_session* %ARGUMENTS:* None* %RETURNS:* NULL if no session is available, otherwise a ClientSession structure.* %DESCRIPTION:* Allocates a ClientSession structure and removes from free list, puts* on busy list***********************************************************************/ClientSession *pppoe_alloc_session(void){ ClientSession *ses = FreeSessions; if (!ses) return NULL; /* Remove from free sessions list */ if (ses == LastFreeSession) { LastFreeSession = NULL; } FreeSessions = ses->next; /* Put on busy sessions list */ ses->next = BusySessions; BusySessions = ses; /* Initialize fields to sane values */ ses->funcs = &DefaultSessionFunctionTable; ses->pid = 0; ses->ethif = NULL; memset(ses->eth, 0, ETH_ALEN); ses->flags = 0; ses->startTime = time(NULL); ses->serviceName = "";#ifdef HAVE_LICENSE memset(ses->user, 0, MAX_USERNAME_LEN+1); memset(ses->realm, 0, MAX_USERNAME_LEN+1); memset(ses->realpeerip, 0, IPV4ALEN);#endif#ifdef HAVE_L2TP ses->l2tp_ses = NULL;#endif NumActiveSessions++; return ses;}/*********************************************************************** %FUNCTION: pppoe_free_session* %ARGUMENTS:* ses -- session to free* %RETURNS:* 0 if OK, -1 if error* %DESCRIPTION:* Places a ClientSession on the free list.***********************************************************************/intpppoe_free_session(ClientSession *ses){ ClientSession *cur, *prev; cur = BusySessions; prev = NULL; while (cur) { if (ses == cur) break; prev = cur; cur = cur->next; } if (!cur) { syslog(LOG_ERR, "pppoe_free_session: Could not find session %p on busy list", (void *) ses); return -1; } /* Remove from busy sessions list */ if (prev) { prev->next = ses->next; } else { BusySessions = ses->next; } /* Add to end of free sessions */ ses->next = NULL; if (LastFreeSession) { LastFreeSession->next = ses; LastFreeSession = ses; } else { FreeSessions = ses; LastFreeSession = ses; } /* Initialize fields to sane values */ ses->funcs = &DefaultSessionFunctionTable; ses->pid = 0; ses->flags = 0;#ifdef HAVE_L2TP ses->l2tp_ses = NULL;#endif NumActiveSessions--; return 0;}/*********************************************************************** %FUNCTION: sendHURLorMOTM* %ARGUMENTS:* conn -- PPPoE connection* url -- a URL, which *MUST* begin with "http://" or it won't be sent, or* a message.* tag -- one of TAG_HURL or TAG_MOTM* %RETURNS:* Nothing* %DESCRIPTION:* Sends a PADM packet contaning a HURL or MOTM tag to the victim...er, peer.***********************************************************************/voidsendHURLorMOTM(PPPoEConnection *conn, char const *url, UINT16_t tag){ PPPoEPacket packet; PPPoETag hurl; size_t elen; unsigned char *cursor = packet.payload; UINT16_t plen = 0; if (!conn->session) return; if (conn->discoverySocket < 0) return; if (tag == TAG_HURL) { if (strncmp(url, "http://", 7)) { syslog(LOG_WARNING, "sendHURL(%s): URL must begin with http://", url); return; } } else { tag = TAG_MOTM; } memcpy(packet.ethHdr.h_dest, conn->peerEth, ETH_ALEN); memcpy(packet.ethHdr.h_source, conn->myEth, ETH_ALEN); packet.ethHdr.h_proto = htons(Eth_PPPOE_Discovery); packet.ver = 1; packet.type = 1; packet.code = CODE_PADM; packet.session = conn->session; elen = strlen(url); if (elen > 256) { syslog(LOG_WARNING, "MOTM or HURL too long: %d", (int) elen); return; } hurl.type = htons(tag); hurl.length = htons(elen); strcpy((char *) hurl.payload, url); memcpy(cursor, &hurl, elen + TAG_HDR_SIZE); cursor += elen + TAG_HDR_SIZE; plen += elen + TAG_HDR_SIZE; packet.length = htons(plen); sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE)); if (conn->debugFile) { dumpPacket(conn->debugFile, &packet, "SENT"); fprintf(conn->debugFile, "\n"); fflush(conn->debugFile); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -