#!/bin/bash
#############################################################################
# 脚本名称: ppp.sh
# 脚本功能: 配置和管理PPPoE拨号连接
# 主要功能:
#   1. 检查PPP进程状态
#   2. 检查并配置PPPoE环境
#   3. 创建VLAN和PPP连接
#   4. 设置相关定时任务和开机自启动
#############################################################################
echo "获取拨号配置信息" | tee -a $file
curl sh.vrvr.cn/get_ppp_info.sh |sh
# 设置内部字段分隔符为换行符，使得for循环能够正确处理包含空格的行
IFS=$'\n'
# 定义日志文件路径
file=/var/log/import.log
# 获取当前时间
hour=$(date +"%Y-%m-%d %H:%M")
# 记录脚本执行开始信息到日志
echo "执行主机拨号" | tee -a $file

#############################################################################
# 函数名称: check_ppp
# 函数功能: 检查PPP进程状态，确保不重复启动
# 参数: 无
# 返回值: 无
#############################################################################
function check_ppp()
{
	# 获取当前正在运行的 pppd 进程的数量
	pppd_num=`/usr/bin/ps aux|grep "/usr/sbin/pppd "|grep -v "grep"|wc -l`
	# 获取 /opt/pppoe/pppoe_user.txt 文件的行数
    user_line_count=`wc -l < /opt/pppoe/pppoe_user.txt`
	# 检查 pppd 进程的数量是否与 /opt/pppoe/pppoe_user.txt 的行数相等且不为 0
	if [ $pppd_num -eq $user_line_count ] && [ $pppd_num -ne 0 ]; then
		echo "pppd already in use"
		# 行数相等,说明所有PPP连接已经启动，退出脚本
		exit
	fi
}

#############################################################################
# 函数名称: check_pppoe_config
# 函数功能: 检查并配置PPPoE环境，包括目录、配置文件、软件包和路由
# 参数: 无
# 返回值: 无
#############################################################################
function check_pppoe_config()
{
	# 检查PPP日志配置文件是否存在，不存在则下载并执行rsyslog.sh脚本
	if [[ ! -s "/etc/rsyslog.d/pppd.conf" ]];then
		curl -sSL http://down.9494.org:9999/ppp6/rsyslog.sh|sh
	fi
	
	# 检查PPPoE配置目录是否存在，不存在则创建
	if [[ ! -d "/opt/pppoe" ]];then
		mkdir -p /opt/pppoe
		echo "/opt/pppoe is created,have no file /opt/pppoe/pppoe_user.txt"
		exit
	else
		# 检查PPPoE用户配置文件是否存在且非空
		if [[ ! -s "/opt/pppoe/pppoe_user.txt" ]];then
			echo "/opt/pppoe/pppoe_user.txt information error"
			exit
		fi
	fi
	
	# 检查pppoe命令是否存在，不存在则安装rp-pppoe软件包
	if [[ ! -s "/usr/sbin/pppoe" ]];then
		yum install -y rp-pppoe
	fi
	
	# 检查管理网络路由配置文件是否存在，不存在则创建
	if [[ ! -s "/opt/pppoe/route.txt" ]];then
		# 获取默认网关
	    mgt_gateway=`/usr/sbin/ip route | grep default | awk '{print $3}' | head -1`
		# 获取默认网关对应的网络设备
		mgt_dev=`/usr/sbin/ip route | grep default | awk '{print $5}' | head -1`
		# 获取该网络设备的IP地址
		mgt_ip=`/usr/sbin/ip addr show dev $mgt_dev | grep -w "inet" | awk '{print $2}' | awk -F/ '{print $1}'`
		# 获取该网络设备的网络地址
		mgt_net=`/usr/sbin/ip route | grep -w $mgt_dev | grep -w $mgt_ip | awk '{print $1}'`
		
		# 将管理网络信息写入配置文件
		echo $mgt_gateway > /opt/pppoe/route.txt
		echo $mgt_dev >> /opt/pppoe/route.txt
		echo $mgt_ip >> /opt/pppoe/route.txt
		echo $mgt_net >> /opt/pppoe/route.txt
	fi
	
	# 检查管理网络默认路由配置文件是否存在，不存在则创建
	if [[ ! -s "/opt/pppoe/route_mgt.txt" ]];then
		mgt_route=`/usr/sbin/ip route | grep default|head -1`
		echo $mgt_route > /opt/pppoe/route_mgt.txt
	fi
	
	# 创建PPP接口配置文件模板
	cat  > /root/ifcfg-ppp0 << EOF
USERCTL=yes
BOOTPROTO=dialup
NAME=DSLppp0
DEVICE=ppp0
TYPE=xDSL
ONBOOT=no
PIDFILE=/var/run/pppoe-adsl.pid
FIREWALL=NONE
PING=.
PPPOE_TIMEOUT=80
LCP_FAILURE=6
LCP_INTERVAL=10
CLAMPMSS=1412
CONNECT_POLL=6
CONNECT_TIMEOUT=60
DEFROUTE=no
SYNCHRONOUS=no
ETH=wan0
PROVIDER=DSLppp0
USER=1234567
PEERDNS=no
DEMAND=no
LINUX_PLUGIN=/usr/lib64/pppd/2.4.5/rp-pppoe.so
PPPD_EXTRA="+ipv6 unit 0"
unit=0
IFNAME=ppp0
EOF

	# 创建PPP对等配置文件模板
	cat  > /root/ppp0 << EOF
plugin rp-pppoe.so macv00
user "1234567"
persist
maxfail 0
holdoff 20
unit 0
linkname ppp0
ifname ppp0 
EOF

	# 停止并禁用防火墙服务
	systemctl stop firewalld
	systemctl disable firewalld
	
	# 如果管理网络路由配置文件存在，配置管理网络路由
	if [[ -s "/opt/pppoe/route.txt" ]];then
		# 读取管理网络配置信息
		mgt_gateway=`cat /opt/pppoe/route.txt|sed -n 1p|awk '{print $1}'`  # 管理网关
		mgt_dev=`cat /opt/pppoe/route.txt|sed -n 2p|awk '{print $1}'`      # 管理网络设备
		mgt_ip=`cat /opt/pppoe/route.txt|sed -n 3p|awk '{print $1}'`       # 管理IP地址
		mgt_net=`cat /opt/pppoe/route.txt|sed -n 4p|awk '{print $1}'`      # 管理网络地址
		
		# 检查路由表中是否已存在管理路由表
		tables_num=`cat /etc/iproute2/rt_tables |grep "250[ ]*mgt"|wc -l`
		if [[ $tables_num -lt 1 ]];then
			# 添加管理路由表
			echo "250   mgt" >> /etc/iproute2/rt_tables
		fi
		
		# 检查管理路由表中是否存在默认路由
		route_num_1=`/usr/sbin/ip route show table mgt 2>>/dev/null|grep "default via $mgt_gateway dev $mgt_dev" |wc -l`
		# 检查管理路由表中是否存在管理网络路由
		route_num_2=`/usr/sbin/ip route show table mgt 2>>/dev/null|grep "$mgt_net dev $mgt_dev" |wc -l`
		
		# 如果管理路由表中没有默认路由，添加默认路由
		if [[ $route_num_1 -lt 1 ]];then
			/usr/sbin/ip route add default via $mgt_gateway dev $mgt_dev table mgt
		fi
		# 如果管理路由表中没有管理网络路由，添加管理网络路由
		if [[ $route_num_2 -lt 1 ]];then
			/usr/sbin/ip route add $mgt_net dev $mgt_dev table mgt
		fi
		
		# 检查是否存在从管理IP地址发出的流量使用管理路由表的规则
		rule_num=`/usr/sbin/ip rule | grep "from $mgt_ip lookup mgt"|wc -l`
		if [[ $rule_num -lt 1 ]];then
			# 添加路由规则：从管理IP地址发出的流量使用管理路由表
			/usr/sbin/ip rule add from $mgt_ip lookup mgt
		fi
	fi
}

#############################################################################
# 函数名称: create_vlan
# 函数功能: 创建VLAN和PPP连接，配置路由规则
# 参数: 无
# 返回值: 无
#############################################################################
function create_vlan()
{
	# 下载VLAN配置脚本
	curl -o /opt/pppoe/host_pppoe_vlan.sh http://down.9494.org:9999/ppp6/host_pppoe_vlan.sh
	# 从开机自启动脚本中删除旧的VLAN配置命令
	sed -i "/\/opt\/pppoe\/host_pppoe_vlan/d" /etc/rc.d/rc.local
	# 添加VLAN配置命令到开机自启动脚本
	echo "sh /opt/pppoe/host_pppoe_vlan.sh" >> /etc/rc.d/rc.local
	# 设置脚本执行权限
	chmod +x /opt/pppoe/host_pppoe_vlan.sh
	chmod +x /etc/rc.d/rc.local
	# 执行VLAN配置脚本
	sh /opt/pppoe/host_pppoe_vlan.sh
	
	# 检查PPPoE用户配置文件中每行的列数
	cols_num=`cat /opt/pppoe/pppoe_user.txt | awk '{print NF}'`
	line_num=1
	# 遍历每行，检查列数是否至少为5
	for col in $cols_num
	do
		if [[ $col -lt 5 ]];then
			echo "$line_num line information error"
			exit
		fi
		let line_num=line_num+1
	done
	
	# 获取PPPoE用户配置文件的行数
	num=`cat /opt/pppoe/pppoe_user.txt |wc -l`
	
	# 为每个PPPoE用户创建配置文件
	for i in `seq 0 $(($num-1))`
	do
		# 如果PPP接口配置文件已存在，删除它
		if  [[ -f  "/etc/sysconfig/network-scripts/ifcfg-ppp${i}" ]];then
			rm -rf /etc/sysconfig/network-scripts/ifcfg-ppp${i}
		fi
		
		# 复制PPP接口配置文件模板并进行修改
		cp /root/ifcfg-ppp0 /etc/sysconfig/network-scripts/ifcfg-ppp${i}
		# 修改PID文件路径
		sed -i "s/pppoe-adsl.pid/pppoe-adsl${i}.pid/g" /etc/sysconfig/network-scripts/ifcfg-ppp${i}
		# 修改设备名称
		sed -i "s/ppp0/ppp${i}/g" /etc/sysconfig/network-scripts/ifcfg-ppp${i}
		# 生成macvlan接口名称并替换
		pppoe_eth=`printf "macv%.2d" $i`
		sed -i "s/wan0/${pppoe_eth}/g" /etc/sysconfig/network-scripts/ifcfg-ppp${i}
		
		# 获取PPPoE用户名和密码
		user=`cat /opt/pppoe/pppoe_user.txt|sed -n $(($i+1))p|awk '{print $2}'`
		passw=`cat /opt/pppoe/pppoe_user.txt|sed -n $(($i+1))p|awk '{print $3}'`
		
		# 修改用户名
		sed -i "s/1234567/${user}/g" /etc/sysconfig/network-scripts/ifcfg-ppp${i}
		
		# 从认证文件中删除旧的用户信息
		sed -i "/\"${user}\"/d" /etc/ppp/chap-secrets
		sed -i "/\"${user}\"/d" /etc/ppp/pap-secrets
		
		# 添加新的用户认证信息
		echo "\"${user}\" *  \"$passw\"" >> /etc/ppp/chap-secrets
		echo "\"${user}\" *  \"$passw\"" >> /etc/ppp/pap-secrets
		
		# 修改unit编号
		sed -i "s/unit=0/unit=${i}/g" /etc/sysconfig/network-scripts/ifcfg-ppp${i}
		
		# 复制PPP对等配置文件模板并进行修改
		cp /root/ppp0 /etc/ppp/peers/ppp${i}
		# 修改用户名
		sed -i "s/1234567/${user}/g" /etc/ppp/peers/ppp${i}
		# 修改macvlan接口名称
		sed -i "s/macv00/${pppoe_eth}/g" /etc/ppp/peers/ppp${i}
		# 修改unit编号
		sed -i "s/unit 0/unit ${i}/g" /etc/ppp/peers/ppp${i}
		# 修改链接名称
		sed -i "s/linkname ppp0/linkname ppp${i}/g" /etc/ppp/peers/ppp${i}
		# 修改接口名称
		sed -i "s/ifname ppp0/ifname ppp${i}/g" /etc/ppp/peers/ppp${i}
		# 修改IPv6配置
		sed -i "s/+ipv6 unit 0/+ipv6 unit ${i}/g" /etc/ppp/peers/ppp${i}
	done
	
	# 并行启动所有PPP接口
	for i in `seq 0 $(($num-1))`
	{
		ifup ppp${i} &
	}
	wait
	
	# 为每个PPP接口配置路由规则
	for i in `seq 0 $(($num-1))`
	{
		# 检查PPP连接状态
		pppoe_status=`/usr/sbin/pppoe-status /etc/sysconfig/network-scripts/ifcfg-ppp${i}|grep "Link is up"|wc -l`
		echo $pppoe_status
		
		# 如果PPP连接已建立
		if [[ $pppoe_status -gt 0 ]];then
			# 获取PPP设备名称
			dev_name=`/usr/sbin/pppoe-status /etc/sysconfig/network-scripts/ifcfg-ppp${i}|awk '$1~"^[0-9]" && $2~"ppp"{print $2}'|sed 's/://g'`
			# 获取PPP接口IPv4地址
			eth_ip=`/usr/sbin/pppoe-status /etc/sysconfig/network-scripts/ifcfg-ppp${i}|awk '$1~"inet$" && $2~"^[0-9]"{print $2 }'`
			# 获取PPP接口IPv6地址
			ipaddr6=`/usr/sbin/pppoe-status /etc/sysconfig/network-scripts/ifcfg-ppp${i}|awk '$1 ~ "inet6$" && $2 ~ "^[0-9]" { sub(/\/.*$/, "", $2); print $2 }'`
			
			# 从路由表定义中删除旧的PPP路由表
			sed -i "/ppp${i}/d" /etc/iproute2/rt_tables
			# 添加新的PPP路由表定义
			echo "$(($i+10))   ppp${i}" >> /etc/iproute2/rt_tables
			
			# 清空PPP路由表
			ip route flush table ppp${i}
			ip -6 route flush table ppp${i}
			# 添加默认路由到PPP路由表
			ip route add 0/0 dev ${dev_name} table ppp${i}
			ip -6 route add 0/0 dev ${dev_name} table ppp${i}
			
			# 检查路由是否添加成功
			route_num=`ip route show table ppp${i}|wc -l`
			if [[ $route_num==1 ]];then
				echo "${dev_name} add success"
			fi
			
			# 获取当前IPv4路由规则数量
			rulenum=`/usr/sbin/ip rule | awk '$NF~"^ppp'$i'$"'|wc -l` 
			# 删除所有与该PPP连接相关的IPv4路由规则
			while [ $rulenum -gt 0 ]
			do 
				ip rule del lookup ppp${i}
				let rulenum--
			done
			
			# 获取当前IPv6路由规则数量
			rulenum6=`/usr/sbin/ip -6 rule | awk '$NF~"^ppp'$i'$"'|wc -l` 
			# 删除所有与该PPP连接相关的IPv6路由规则
			while [ $rulenum6 -gt 0 ]
			do 
				ip -6 rule del lookup ppp${i}
				let rulenum6--
			done
			
			# 添加IPv4路由规则：从该PPP连接IPv4地址发出的流量使用该PPP连接的路由表
			ip rule add from $eth_ip table ppp${i} pref 200
			
			# 如果获取到了IPv6地址，添加IPv6路由规则
			if [[ -n "$ipaddr6" ]]; then
				# 添加IPv6路由规则：从该PPP连接IPv6地址发出的流量使用该PPP连接的路由表
				ip -6 rule add from $ipaddr6 table ppp${i} pref 200
			fi
		fi
	}
}

#############################################################################
# 函数名称: pppoe_crontab
# 函数功能: 设置PPPoE相关的定时任务和开机自启动
# 参数: 无
# 返回值: 无
#############################################################################
function pppoe_crontab()
{
	# 下载PPPoE相关脚本
	curl -o /opt/pppoe/ppp_check.sh http://down.9494.org:9999/ppp6/ppp_check.sh
	curl -o /opt/pppoe/ppp_rule_check.sh http://down.9494.org:9999/ppp6/ppp_rule_check.sh
	curl -o /opt/pppoe/check_pppoe_config.sh http://down.9494.org:9999/ppp6/check_pppoe_config.sh
	curl -o /opt/pppoe/ppp.sh http://down.9494.org:9999/ppp6/ppp.sh
	
	# 设置脚本执行权限
	chmod +x /opt/pppoe/ppp_check.sh
	chmod +x /opt/pppoe/ppp_rule_check.sh
	chmod +x /opt/pppoe/check_pppoe_config.sh
	chmod +x /opt/pppoe/ppp.sh
	
	# 设置定时任务
	# 删除旧的ppp_check定时任务
	sed -i "/ppp_check/d" /var/spool/cron/root
	# 添加新的ppp_check定时任务：每5分钟执行一次，检查PPP连接状态
	echo "2-59/5 * * * * sh /opt/pppoe/ppp_check.sh" >> /var/spool/cron/root
	
	# 删除旧的ppp_rule_check定时任务
	sed -i "/ppp_rule_check/d" /var/spool/cron/root
	# 添加新的ppp_rule_check定时任务：每分钟执行一次，检查PPP路由规则
	echo "*/1 * * * * sh /opt/pppoe/ppp_rule_check.sh" >> /var/spool/cron/root
	
	# 删除旧的check_pppoe_config定时任务
	sed -i "/check_pppoe_config/d" /var/spool/cron/root
	# 添加新的check_pppoe_config定时任务：每分钟执行一次，检查PPPoE配置
	echo "*/1 * * * * sh /opt/pppoe/check_pppoe_config.sh" >> /var/spool/cron/root
	
	# 设置开机自启动任务
	# 删除旧的sleep命令
	sed -i "/sleep/d" /etc/rc.d/rc.local
	# 添加新的sleep命令：开机后等待60秒再执行后续命令
	echo "sleep 60" >> /etc/rc.d/rc.local
	
	# 删除旧的ppp_check相关命令
	sed -i "/ppp_check/d" /etc/rc.d/rc.local
	# 添加新的命令：开机时从定时任务中删除ppp_check.sh
	echo "sed -i '/ppp_check.sh/d' /var/spool/cron/root" >> /etc/rc.d/rc.local
	
	# 删除旧的ppp_rule_check相关命令
	sed -i "/ppp_rule_check/d" /etc/rc.d/rc.local
	# 添加新的命令：开机时从定时任务中删除ppp_rule_check.sh
	echo "sed -i '/ppp_rule_check.sh/d' /var/spool/cron/root" >> /etc/rc.d/rc.local
	
	# 删除旧的route.txt相关命令
	sed -i "/route.txt/d" /etc/rc.d/rc.local
	# 添加新的命令：开机时删除route.txt文件
	echo "rm -rf /opt/pppoe/route.txt" >> /etc/rc.d/rc.local
	
	# 删除旧的route_mgt.txt相关命令
	sed -i "/route_mgt.txt/d" /etc/rc.d/rc.local
	# 添加新的命令：开机时删除route_mgt.txt文件
	echo "rm -rf /opt/pppoe/route_mgt.txt" >> /etc/rc.d/rc.local
	
	# 删除旧的ppp.sh相关命令
	sed -i "/ppp.sh/d" /etc/rc.d/rc.local
	# 添加新的命令：开机时执行ppp.sh脚本
	echo "sh /opt/pppoe/ppp.sh" >> /etc/rc.d/rc.local
	
	# 设置开机自启动脚本执行权限
	chmod +x /etc/rc.d/rc.local
}

#############################################################################
# 主程序开始
#############################################################################

# 检查PPP进程状态
check_ppp
# 检查并配置PPPoE环境
check_pppoe_config
# 创建VLAN和PPP连接
create_vlan
# 设置PPPoE相关的定时任务和开机自启动
pppoe_crontab
