From 8ab8c604d0642c473d3a395b3421afa51694af9c Mon Sep 17 00:00:00 2001 From: kejun.gao Date: Wed, 29 Aug 2012 06:06:21 +0000 Subject: 1. Save PADT when PDAS received. 2. Send saved PADT by command "pcli terminate". 3. In init.rc, add service: service close_pppoe /system/bin/pcli terminate class core oneshot on property:net.eth0.status=up start close_pppoe 4. In EthernetStateTraker.java, when ether wire is detected, change net.eth0.status as up. --- diff --git a/Android.mk b/Android.mk index 95cc205..3d4819a 100755 --- a/Android.mk +++ b/Android.mk @@ -48,7 +48,9 @@ include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS) -LOCAL_SRC_FILES:= jni/src/pppoe_cli.c +LOCAL_SRC_FILES:= jni/src/pppoe_cli.c \ + jni/src/common.c + LOCAL_MODULE_TAGS := optional LOCAL_MODULE := pcli LOCAL_SHARED_LIBRARIES := libcutils libnetutils diff --git a/jni/src/common.c b/jni/src/common.c index b8c53fd..36f644a 100755 --- a/jni/src/common.c +++ b/jni/src/common.c @@ -45,6 +45,7 @@ static char const RCSID[] = #include #include +#include "../../ppp/pppd/pathnames.h" /* Are we running SUID or SGID? */ int IsSetID = 0; @@ -570,6 +571,164 @@ sendPADT(PPPoEConnection *conn, char const *msg) syslog(LOG_INFO,"Sent PADT"); } + +int +getRawSocket(char const *ifname) +{ + int ret; + int optval=1; + int fd; + struct ifreq ifr; + int domain, stype; + + struct sockaddr_ll sa; + + memset(&sa, 0, sizeof(sa)); + + domain = PF_PACKET; + stype = SOCK_RAW; + + fd = socket(domain, stype, htons(ETH_PPPOE_DISCOVERY)); + if (fd < 0) { + syslog(LOG_INFO,"failed to create raw socket"); + return -1; + } + + ret = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)); + if (ret < 0) { + syslog(LOG_INFO,"failed to setsockopt"); + return -1; + } + + + /* Get interface index */ + sa.sll_family = AF_PACKET; + sa.sll_protocol = htons(ETH_PPPOE_DISCOVERY); + + strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + ret = ioctl(fd, SIOCGIFINDEX, &ifr); + if (ret < 0) { + syslog(LOG_INFO,"failed to ioctl"); + return -1; + } + sa.sll_ifindex = ifr.ifr_ifindex; + + /* We're only interested in packets on specified interface */ + ret = bind(fd, (struct sockaddr *) &sa, sizeof(sa)); + if (ret < 0) { + syslog(LOG_INFO,"failed to bind"); + return -1; + } + + return fd; +} + + +void +sendSavedPADT(char *padt_file) +{ + FILE *file_fd = NULL; + char *packet; + long len; + int fd; + + file_fd = fopen(padt_file, "r"); + if (!file_fd) { + syslog(LOG_INFO,"failed to read padt"); + return; + } + + fseek(file_fd, 0, SEEK_END); + len = ftell(file_fd); + if (len < 0) { + goto free_file_fd; + } + + packet = malloc(len); + if (!packet){ + syslog(LOG_INFO, "sendSavedPADT: failed to malloc"); + goto free_file_fd; + } + + fseek(file_fd, 0, SEEK_SET); + fread(packet, 1, len, file_fd); + + fd = getRawSocket("eth0"); + if ( fd < 0){ + syslog(LOG_INFO, "sendSavedPADT: failed to getRawSocket"); + goto free_packet; + + } + send( fd, packet, len, 0); + syslog(LOG_INFO, "Send SavedPADT(fd = %d) by eth0", fd); + + close(fd); + +free_packet: + free(packet); + +free_file_fd: + fclose(file_fd); + } + + +void +savePADT(PPPoEConnection *conn, char const *msg) +{ + FILE *padt_file_bin = NULL; + PPPoEPacket packet; + unsigned char *cursor = packet.payload; + + UINT16_t plen = 0; + + 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_PADT; + packet.session = conn->session; + + /* Reset Session to zero so there is no possibility of + recursive calls to this function by any signal handler */ + //conn->session = 0; + + /* If we're using Host-Uniq, copy it over */ + if (conn->useHostUniq) { + PPPoETag hostUniq; + pid_t pid = getpid(); + hostUniq.type = htons(TAG_HOST_UNIQ); + hostUniq.length = htons(sizeof(pid)); + memcpy(hostUniq.payload, &pid, sizeof(pid)); + memcpy(cursor, &hostUniq, sizeof(pid) + TAG_HDR_SIZE); + cursor += sizeof(pid) + TAG_HDR_SIZE; + plen += sizeof(pid) + TAG_HDR_SIZE; + } + + /* Copy error message */ + if (msg) { + PPPoETag err; + size_t elen = strlen(msg); + err.type = htons(TAG_GENERIC_ERROR); + err.length = htons(elen); + strcpy((char *) err.payload, msg); + memcpy(cursor, &err, elen + TAG_HDR_SIZE); + cursor += elen + TAG_HDR_SIZE; + plen += elen + TAG_HDR_SIZE; + } + + packet.length = htons(plen); + + padt_file_bin = fopen(_ROOT_PATH "/etc/ppp/padt_bin", "w"); + if (!padt_file_bin) { + syslog(LOG_INFO,"failed to save padt_bin"); + } + fwrite(&packet, (int) (plen + HDR_SIZE), 1, padt_file_bin); + fflush(padt_file_bin); + fclose(padt_file_bin); +} + /*********************************************************************** *%FUNCTION: sendPADTf *%ARGUMENTS: diff --git a/jni/src/discovery.c b/jni/src/discovery.c index c92ceef..63884bc 100755 --- a/jni/src/discovery.c +++ b/jni/src/discovery.c @@ -652,6 +652,7 @@ waitForPADS(PPPoEConnection *conn, int timeout) * Performs the PPPoE discovery phase ***********************************************************************/ static struct timeval current_time; +void savePADT(PPPoEConnection *conn, char const *msg); static int g_padi_sent = 0; void @@ -730,6 +731,8 @@ discovery(PPPoEConnection *conn) timeout *= 2; } while (conn->discoveryState == STATE_SENT_PADR); + savePADT(conn, "RP-PPPoE: Received gaokj to disconnect"); + /* We're done. */ conn->discoveryState = STATE_SESSION; return; diff --git a/jni/src/pppoe.c b/jni/src/pppoe.c index 5809f92..6ad8293 100755 --- a/jni/src/pppoe.c +++ b/jni/src/pppoe.c @@ -645,7 +645,7 @@ main(int argc, char *argv[]) } else { conn.discoverySocket = openInterface(conn.ifName, Eth_PPPOE_Discovery, conn.myEth); - syslog( LOG_INFO, "discovery\n"); + syslog( LOG_INFO, "begin discovery conn.myEth =%p\n", conn.myEth); discovery(&conn); } if (optSkipSession) { diff --git a/jni/src/pppoe_cli.c b/jni/src/pppoe_cli.c index 9c23af5..e453416 100755 --- a/jni/src/pppoe_cli.c +++ b/jni/src/pppoe_cli.c @@ -35,10 +35,19 @@ int main(int argc, char *argv[]) struct netwrapper_ctrl * ctrl; if (argc < 2 || (0 != strcmp( "connect", argv[1]) && - 0 != strcmp( "disconnect", argv[1]) )) { + 0 != strcmp( "disconnect", argv[1] ) && + 0 != strcmp( "terminate", argv[1] ))) { usage(); return -2; } + + if (0 == strcmp( "terminate", argv[1] )) { + for ( i = 0; i < 3; i++ ) { + sendSavedPADT(_ROOT_PATH "/etc/ppp/padt_bin"); + sleep(1); + } + return 0; + } ctrl = netwrapper_ctrl_open(_ROOT_PATH "/etc/ppp/pppcli", PPPOE_WRAPPER_SERVER_PATH); if (ctrl == NULL) { -- cgit