/********************************************************************** *%FUNCTION: fatalSys *%ARGUMENTS: * str -- error message *%RETURNS: * Nothing *%DESCRIPTION: * Prints a message plus the errno value to stderr and syslog and exits. ***********************************************************************/ void fatalSys(char const *str) { char buf[1024]; int i = errno; sprintf(buf, "%.256s: %.256s", str, strerror(i)); printErr(buf); sprintf(buf, "RP-PPPoE: %.256s: %.256s", str, strerror(i)); sendPADT(conn, buf); exit(1); }
static void close_conn(int send_padt) { if (!conn) return; if (conn->sessionSocket != -1) { close(conn->sessionSocket); conn->sessionSocket = -1; } if (send_padt) { /* Send PADT to reset the session unresponsive at buggy nas */ sendPADT(conn, NULL); } if (!existingSession && conn->discoverySocket != -1) { close(conn->discoverySocket); conn->discoverySocket = -1; } }
/********************************************************************** * %FUNCTION: PPPOEDisconnectDevice * %ARGUMENTS: * None * %RETURNS: * Nothing * %DESCRIPTION: * Disconnects PPPoE device ***********************************************************************/ static void PPPOEDisconnectDevice(void) { struct sockaddr_pppox sp; sp.sa_family = AF_PPPOX; sp.sa_protocol = PX_PROTO_OE; sp.sa_addr.pppoe.sid = 0; memcpy(sp.sa_addr.pppoe.dev, conn->ifName, IFNAMSIZ); memcpy(sp.sa_addr.pppoe.remote, conn->peerEth, ETH_ALEN); if (connect(conn->sessionSocket, (struct sockaddr *) &sp, sizeof(struct sockaddr_pppox)) < 0) { if (errno != EALREADY) warn("Failed to disconnect PPPoE socket: %d %m", errno); } close(conn->sessionSocket); conn->sessionSocket = -1; /* Send PADT to reset the session unresponsive at buggy nas */ sendPADT(conn, NULL); if (!existingSession) { close(conn->discoverySocket); conn->discoverySocket = -1; } }
/********************************************************************** *%FUNCTION: discovery *%ARGUMENTS: * conn -- PPPoE connection info structure *%RETURNS: * Nothing *%DESCRIPTION: * Performs the PPPoE discovery phase ***********************************************************************/ void discovery(PPPoEConnection *conn) { int padiAttempts = 0; int padrAttempts = 0; int timeout = PADI_TIMEOUT; /* Skip discovery and don't open discovery socket? */ if (conn->skipDiscovery && conn->noDiscoverySocket) { conn->discoveryState = STATE_SESSION; return; } conn->discoverySocket = openInterface(conn->ifName, Eth_PPPOE_Discovery, conn->myEth); /* Skip discovery? */ if (conn->skipDiscovery) { conn->discoveryState = STATE_SESSION; if (conn->killSession) { sendPADT(conn, "RP-PPPoE: Session killed manually"); exit(0); } return; } do { padiAttempts++; if (padiAttempts > MAX_PADI_ATTEMPTS) { system("rm /etc/ppp/connectfile"); rp_fatal("Timeout waiting for PADO packets0"); } sendPADI(conn); conn->discoveryState = STATE_SENT_PADI; waitForPADO(conn, timeout); #if 0 // RexHua to Reduce connect time /* If we're just probing for access concentrators, don't do exponential backoff. This reduces the time for an unsuccessful probe to 15 seconds. */ if (!conn->printACNames) { timeout *= 2; } #endif if (conn->printACNames && conn->numPADOs) { break; } } while (conn->discoveryState == STATE_SENT_PADI); /* If we're only printing access concentrator names, we're done */ if (conn->printACNames) { printf("--------------------------------------------------\n"); exit(0); } timeout = PADI_TIMEOUT; do { padrAttempts++; if (padrAttempts > MAX_PADI_ATTEMPTS) { rp_fatal("Timeout waiting for PADS packets"); } sendPADR(conn); conn->discoveryState = STATE_SENT_PADR; waitForPADS(conn, timeout); #if 0 // RexHua to Reduce connect time timeout *= 2; #endif } while (conn->discoveryState == STATE_SENT_PADR); /* We're done. */ conn->discoveryState = STATE_SESSION; return; }
/********************************************************************** * %FUNCTION: PPPOEConnectDevice * %ARGUMENTS: * None * %RETURNS: * Non-negative if all goes well; -1 otherwise * %DESCRIPTION: * Connects PPPoE device. ***********************************************************************/ static int PPPOEConnectDevice(void) { struct sockaddr_pppox sp; struct ifreq ifr; int s; /* Restore configuration */ lcp_allowoptions[0].mru = conn->mtu; lcp_wantoptions[0].mru = conn->mru; /* Update maximum MRU */ s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { error("Can't get MTU for %s: %m", conn->ifName); return -1; } strncpy(ifr.ifr_name, conn->ifName, sizeof(ifr.ifr_name)); if (ioctl(s, SIOCGIFMTU, &ifr) < 0) { error("Can't get MTU for %s: %m", conn->ifName); close(s); return -1; } close(s); if (lcp_allowoptions[0].mru > ifr.ifr_mtu - TOTAL_OVERHEAD) { lcp_allowoptions[0].mru = ifr.ifr_mtu - TOTAL_OVERHEAD; } if (lcp_wantoptions[0].mru > ifr.ifr_mtu - TOTAL_OVERHEAD) { lcp_wantoptions[0].mru = ifr.ifr_mtu - TOTAL_OVERHEAD; } /* Open session socket before discovery phase, to avoid losing session */ /* packets sent by peer just after PADS packet (noted on some Cisco */ /* server equipment). */ /* Opening this socket just before waitForPADS in the discovery() */ /* function would be more appropriate, but it would mess-up the code */ conn->sessionSocket = socket(AF_PPPOX, SOCK_STREAM, PX_PROTO_OE); if (conn->sessionSocket < 0) { error("Failed to create PPPoE socket: %m"); return -1; } if (acName) { SET_STRING(conn->acName, acName); } if (pppd_pppoe_service) { SET_STRING(conn->serviceName, pppd_pppoe_service); } strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam)); if (existingSession) { unsigned int mac[ETH_ALEN]; int i, ses; if (sscanf(existingSession, "%d:%x:%x:%x:%x:%x:%x", &ses, &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) != 7) { fatal("Illegal value for rp_pppoe_sess option"); } conn->session = htons(ses); for (i=0; i<ETH_ALEN; i++) { conn->peerEth[i] = (unsigned char) mac[i]; } } else { conn->discoverySocket = openInterface(conn->ifName, Eth_PPPOE_Discovery, conn->myEth, NULL); discovery(conn); if (conn->discoveryState != STATE_SESSION) { error("Unable to complete PPPoE Discovery"); goto ERROR; } } /* Set PPPoE session-number for further consumption */ ppp_session_number = ntohs(conn->session); sp.sa_family = AF_PPPOX; sp.sa_protocol = PX_PROTO_OE; sp.sa_addr.pppoe.sid = conn->session; memcpy(sp.sa_addr.pppoe.dev, conn->ifName, IFNAMSIZ); memcpy(sp.sa_addr.pppoe.remote, conn->peerEth, ETH_ALEN); /* Set remote_number for ServPoET */ sprintf(remote_number, "%02X:%02X:%02X:%02X:%02X:%02X", (unsigned) conn->peerEth[0], (unsigned) conn->peerEth[1], (unsigned) conn->peerEth[2], (unsigned) conn->peerEth[3], (unsigned) conn->peerEth[4], (unsigned) conn->peerEth[5]); warn("Connected to %02X:%02X:%02X:%02X:%02X:%02X via interface %s", (unsigned) conn->peerEth[0], (unsigned) conn->peerEth[1], (unsigned) conn->peerEth[2], (unsigned) conn->peerEth[3], (unsigned) conn->peerEth[4], (unsigned) conn->peerEth[5], conn->ifName); script_setenv("MACREMOTE", remote_number, 0); if (connect(conn->sessionSocket, (struct sockaddr *) &sp, sizeof(struct sockaddr_pppox)) < 0) { error("Failed to connect PPPoE socket: %d %m", errno); goto ERROR; } return conn->sessionSocket; ERROR: close(conn->sessionSocket); conn->sessionSocket = -1; /* Send PADT to reset the session unresponsive at buggy nas */ sendPADT(conn, NULL); if (!existingSession) { close(conn->discoverySocket); conn->discoverySocket = -1; } return -1; }
/********************************************************************** * %FUNCTION: PPPOEConnectDevice * %ARGUMENTS: * None * %RETURNS: * Non-negative if all goes well; -1 otherwise * %DESCRIPTION: * Connects PPPoE device. ***********************************************************************/ static int PPPOEConnectDevice(void) { struct sockaddr_pppox sp; PPPoEConnection reconn ; memset(&reconn,0,sizeof(reconn)); strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam)); if (existingSession) { unsigned int mac[ETH_ALEN]; int i, ses; if (sscanf(existingSession, "%d:%x:%x:%x:%x:%x:%x", &ses, &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) != 7) { fatal("Illegal value for rp_pppoe_sess option"); } conn->session = htons(ses); for (i=0; i<ETH_ALEN; i++) { conn->peerEth[i] = (unsigned char) mac[i]; } } else { memcpy(&reconn,conn,sizeof(reconn)); reconn.discoverySocket = openInterface(reconn.ifName, Eth_PPPOE_Discovery, reconn.myEth); sendPADT(&reconn, NULL); close(reconn.discoverySocket); sleep(3); discovery(conn); if (conn->discoveryState != STATE_SESSION) { error("Unable to complete PPPoE Discovery"); return -1; } } /* Set PPPoE session-number for further consumption */ ppp_session_number = ntohs(conn->session); /* Make the session socket */ conn->sessionSocket = socket(AF_PPPOX, SOCK_STREAM, PX_PROTO_OE); if (conn->sessionSocket < 0) { error("Failed to create PPPoE socket: %m"); goto errout; } sp.sa_family = AF_PPPOX; sp.sa_protocol = PX_PROTO_OE; sp.sa_addr.pppoe.sid = conn->session; memcpy(sp.sa_addr.pppoe.dev, conn->ifName, IFNAMSIZ); memcpy(sp.sa_addr.pppoe.remote, conn->peerEth, ETH_ALEN); /* Set remote_number for ServPoET */ sprintf(remote_number, "%02X:%02X:%02X:%02X:%02X:%02X", (unsigned) conn->peerEth[0], (unsigned) conn->peerEth[1], (unsigned) conn->peerEth[2], (unsigned) conn->peerEth[3], (unsigned) conn->peerEth[4], (unsigned) conn->peerEth[5]); warn("Connected to %02X:%02X:%02X:%02X:%02X:%02X via interface %s", (unsigned) conn->peerEth[0], (unsigned) conn->peerEth[1], (unsigned) conn->peerEth[2], (unsigned) conn->peerEth[3], (unsigned) conn->peerEth[4], (unsigned) conn->peerEth[5], conn->ifName); if (connect(conn->sessionSocket, (struct sockaddr *) &sp, sizeof(struct sockaddr_pppox)) < 0) { error("Failed to connect PPPoE socket: %d %m", errno); close(conn->sessionSocket); goto errout; } return conn->sessionSocket; errout: if (conn->discoverySocket >= 0) { sendPADT(conn, NULL); close(conn->discoverySocket); conn->discoverySocket = -1; } return -1; }
/********************************************************************** *%FUNCTION: discovery *%ARGUMENTS: * conn -- PPPoE connection info structure *%RETURNS: * Nothing *%DESCRIPTION: * Performs the PPPoE discovery phase ***********************************************************************/ void discovery(PPPoEConnection *conn) { int padiAttempts = 0; int padrAttempts = 0; int timeout = conn->discoveryTimeout; /* Skip discovery? */ if (conn->skipDiscovery) { conn->discoveryState = STATE_SESSION; if (conn->killSession) { sendPADT(conn, "RP-PPPoE: Session killed manually"); exit(0); } return; } do { padiAttempts++; if (padiAttempts > MAX_PADI_ATTEMPTS) { if (persist) { padiAttempts = 0; timeout = conn->discoveryTimeout; printErr("Timeout waiting for PADO packets"); } else { rp_fatal("Timeout waiting for PADO packets"); } } sendPADI(conn); conn->discoveryState = STATE_SENT_PADI; waitForPADO(conn, timeout); /* If we're just probing for access concentrators, don't do exponential backoff. This reduces the time for an unsuccessful probe to 15 seconds. */ if (!conn->printACNames) { timeout *= 2; } if (conn->printACNames && conn->numPADOs) { break; } } while (conn->discoveryState == STATE_SENT_PADI); /* If we're only printing access concentrator names, we're done */ if (conn->printACNames) { exit(0); } timeout = conn->discoveryTimeout; do { padrAttempts++; if (padrAttempts > MAX_PADI_ATTEMPTS) { if (persist) { padrAttempts = 0; timeout = conn->discoveryTimeout; printErr("Timeout waiting for PADS packets"); } else { rp_fatal("Timeout waiting for PADS packets"); } } sendPADR(conn); conn->discoveryState = STATE_SENT_PADR; waitForPADS(conn, timeout); timeout *= 2; } while (conn->discoveryState == STATE_SENT_PADR); /* We're done. */ conn->discoveryState = STATE_SESSION; return; }
/********************************************************************** *%FUNCTION: discovery *%ARGUMENTS: * conn -- PPPoE connection info structure *%RETURNS: * Nothing *%DESCRIPTION: * Performs the PPPoE discovery phase ***********************************************************************/ void discovery(PPPoEConnection *conn) { int padiAttempts = 0; int padrAttempts = 0; int timeout = PADI_TIMEOUT; /* Skip discovery and don't open discovery socket? */ if (conn->skipDiscovery && conn->noDiscoverySocket) { conn->discoveryState = STATE_SESSION; PPPD_DEBUG(printf("%s %d\n",__FILE__,__LINE__)); return; } conn->discoverySocket = openInterface(conn->ifName, Eth_PPPOE_Discovery, conn->myEth); /* Skip discovery? */ if (conn->skipDiscovery) { conn->discoveryState = STATE_SESSION; if (conn->killSession) { sendPADT(conn, "RP-PPPoE: Session killed manually"); exit(0); } PPPD_DEBUG(printf("%s %d\n",__FILE__,__LINE__)); return; } do { PPPD_DEBUG(printf("%s %d\n",__FILE__,__LINE__)); padiAttempts++; if (padiAttempts > MAX_PADI_ATTEMPTS) { rp_fatal("Timeout waiting for PADO packets"); } sendPADI(conn); conn->discoveryState = STATE_SENT_PADI; waitForPADO(conn, timeout); /* If we're just probing for access concentrators, don't do exponential backoff. This reduces the time for an unsuccessful probe to 15 seconds. */ if (!conn->printACNames) { timeout *= 2; } if (conn->printACNames && conn->numPADOs) { break; } } while (conn->discoveryState == STATE_SENT_PADI); /* If we're only printing access concentrator names, we're done */ if (conn->printACNames) { printf("--------------------------------------------------\n"); exit(0); } PPPD_DEBUG(printf("%s %d\n",__FILE__,__LINE__)); timeout = PADI_TIMEOUT; do { PPPD_DEBUG(printf("%s %d\n",__FILE__,__LINE__)); padrAttempts++; if (padrAttempts > MAX_PADI_ATTEMPTS) { rp_fatal("Timeout waiting for PADS packets"); } sendPADR(conn); conn->discoveryState = STATE_SENT_PADR; waitForPADS(conn, timeout); timeout *= 2; } while (conn->discoveryState == STATE_SENT_PADR); /* We're done. */ free(conn->serviceName);//mcli conn->serviceName=NULL;//mcli conn->discoveryState = STATE_SESSION; PPPD_DEBUG(printf("%s %d\n",__FILE__,__LINE__)); return; }
/********************************************************************** * %FUNCTION: PPPOEConnectDevice * %ARGUMENTS: * None * %RETURNS: * Non-negative if all goes well; -1 otherwise * %DESCRIPTION: * Connects PPPoE device. ***********************************************************************/ static int PPPOEConnectDevice(void) { struct sockaddr_pppox sp; static int qosidx=6410; strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam)); if (existingSession) { unsigned int mac[ETH_ALEN]; int i, ses; if (sscanf(existingSession, "%d:%x:%x:%x:%x:%x:%x", &ses, &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) != 7) { fatal("Illegal value for rp_pppoe_sess option"); } conn->session = htons(ses); for (i=0; i<ETH_ALEN; i++) { conn->peerEth[i] = (unsigned char) mac[i]; } } else { discovery(conn); if (conn->discoveryState != STATE_SESSION) { error("Unable to complete PPPoE Discovery"); return -1; } } /* Set PPPoE session-number for further consumption */ ppp_session_number = ntohs(conn->session); /* Make the session socket */ conn->sessionSocket = socket(AF_PPPOX, SOCK_STREAM, PX_PROTO_OE); if (conn->sessionSocket < 0) { error("Failed to create PPPoE socket: %m"); goto errout; } sp.sa_family = AF_PPPOX; sp.sa_protocol = PX_PROTO_OE; sp.sa_addr.pppoe.sid = conn->session; memcpy(sp.sa_addr.pppoe.dev, conn->ifName, IFNAMSIZ); memcpy(sp.sa_addr.pppoe.remote, conn->peerEth, ETH_ALEN); /* Set remote_number for ServPoET */ sprintf(remote_number, "%02X:%02X:%02X:%02X:%02X:%02X", (unsigned) conn->peerEth[0], (unsigned) conn->peerEth[1], (unsigned) conn->peerEth[2], (unsigned) conn->peerEth[3], (unsigned) conn->peerEth[4], (unsigned) conn->peerEth[5]); warn("Connected to %02X:%02X:%02X:%02X:%02X:%02X via interface %s", (unsigned) conn->peerEth[0], (unsigned) conn->peerEth[1], (unsigned) conn->peerEth[2], (unsigned) conn->peerEth[3], (unsigned) conn->peerEth[4], (unsigned) conn->peerEth[5], conn->ifName); script_setenv("MACREMOTE", remote_number, 0); if (connect(conn->sessionSocket, (struct sockaddr *) &sp, sizeof(struct sockaddr_pppox)) < 0) { fatal("Failed to connect PPPoE socket: %d %m", errno); close(conn->sessionSocket); goto errout; } #ifdef HAVE_AQOS if (bandwidthup!=0 && bandwidthdown!=0) { char uplevel[64]; char downlevel[64]; char mac[64]; sprintf(mac, MACSTR, MAC2STR(conn->myEth)); sprintf(uplevel,"%d",bandwidthup/1000); sprintf(downlevel,"%d",bandwidthdown/1000); fprintf(stderr,"use bandwidth down value to %d\n",bandwidthdown); fprintf(stderr,"use bandwidth up value to %d\n",bandwidthdown); int ret = addrule(mac,uplevel,downlevel); if (!ret) { qosidx+=10; if (qosidx>8190) qosidx=0; add_usermac(mac, qosidx, uplevel,downlevel,"0" ); }else if (ret>1) { system("startstop_f wshaper"); } } #endif return conn->sessionSocket; errout: if (conn->discoverySocket >= 0) { sendPADT(conn, NULL); close(conn->discoverySocket); conn->discoverySocket = -1; } return -1; }
/********************************************************************** *%FUNCTION: discovery *%ARGUMENTS: * conn -- PPPoE connection info structure *%RETURNS: * Nothing *%DESCRIPTION: * Performs the PPPoE discovery phase ***********************************************************************/ void discovery(PPPoEConnection *conn) { int padiAttempts; int padrAttempts; int timeout = conn->discoveryTimeout; /* Skip discovery? */ if (conn->skipDiscovery) { conn->discoveryState = STATE_SESSION; if (conn->killSession) { sendPADT(conn, "RP-PPPoE: Session killed manually"); exit(0); } return; } SEND_PADI: padiAttempts = 0; do { #ifdef PLUGIN if (got_sigterm || got_sighup) return; #endif padiAttempts++; if (padiAttempts > MAX_PADI_ATTEMPTS) { if (persist) { padiAttempts = 0; timeout = conn->discoveryTimeout; printErr("Timeout waiting for PADO packets"); } else { #ifdef PLUGIN printErr("Timeout waiting for PADO packets"); return; #else rp_fatal("Timeout waiting for PADO packets"); #endif } } sendPADI(conn); conn->discoveryState = STATE_SENT_PADI; waitForPADO(conn, timeout); /* If we're just probing for access concentrators, don't do exponential backoff. This reduces the time for an unsuccessful probe to 15 seconds. */ if (!conn->printACNames) { timeout *= 2; } if (conn->printACNames && conn->numPADOs) { break; } } while (conn->discoveryState == STATE_SENT_PADI); /* If we're only printing access concentrator names, we're done */ if (conn->printACNames) { exit(0); } timeout = conn->discoveryTimeout; padrAttempts = 0; do { #ifdef PLUGIN if (got_sigterm || got_sighup) return; #endif padrAttempts++; if (padrAttempts > MAX_PADI_ATTEMPTS) { if (persist) { padrAttempts = 0; timeout = conn->discoveryTimeout; printErr("Timeout waiting for PADS packets"); /* Go back to sending PADI again */ goto SEND_PADI; } else { #ifdef PLUGIN printErr("Timeout waiting for PADS packets"); return; #else rp_fatal("Timeout waiting for PADS packets"); #endif } } sendPADR(conn); conn->discoveryState = STATE_SENT_PADR; waitForPADS(conn, timeout); timeout *= 2; } while (conn->discoveryState == STATE_SENT_PADR); #ifdef PLUGIN if (!conn->seenMaxPayload) { /* RFC 4638: MUST limit MTU/MRU to 1492 */ if (lcp_allowoptions[0].mru > ETH_PPPOE_MTU) lcp_allowoptions[0].mru = ETH_PPPOE_MTU; if (lcp_wantoptions[0].mru > ETH_PPPOE_MTU) lcp_wantoptions[0].mru = ETH_PPPOE_MTU; } #endif /* We're done. */ conn->discoveryState = STATE_SESSION; return; }