commit 81d861cb46e9eef96ec161e8ceb252beaadea3ec
parent 14ec50f379a418383e2aa0203e01ef45b5cbd789
Author: oblique <psyberbits@gmail.com>
Date: Fri, 5 Sep 2014 01:53:42 +0300
Reimplementation of 6a3e1d98 commit
With the 6a3e1d98 commit NetworkManager was throwing an assertion so
we take a different approach when we create the bridge interface.
Also if the <interface-with-internet> is already a bridge interface
we skip creation.
The new approach is:
1) Save the IPs and route table of INTERNET_IFACE
2) If NetworkManager is running set INTERNET_IFACE as unmanaged
3) Create BRIDGE_IFACE and add INTERNET_IFACE to it
4) Set the previously saved IPs and route table to BRIDGE_IFACE
Better fix #19
Diffstat:
M | README.md | | | 3 | +++ |
M | create_ap | | | 166 | +++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------- |
2 files changed, 111 insertions(+), 58 deletions(-)
diff --git a/README.md b/README.md
@@ -54,6 +54,9 @@
### Bridged Internet sharing:
create_ap -m bridge wlan0 eth0 MyAccessPoint MyPassPhrase
+### Bridged Internet sharing (pre-configured bridge interface):
+ create_ap -m bridge wlan0 br0 MyAccessPoint MyPassPhrase
+
### Internet sharing from the same WiFi interface:
create_ap wlan0 wlan0 MyAccessPoint MyPassPhrase
diff --git a/create_ap b/create_ap
@@ -43,6 +43,8 @@ usage() {
echo " * If you're not using the --no-virt option, then you can create an AP with the same"
echo " interface you are getting your Internet connection."
echo " * You can pass your SSID and password through pipe or through arguments (see examples)."
+ echo " * On bridge method if the <interface-with-internet> is not a bridge interface, then"
+ echo " a bridge interface is created automatically."
echo
echo "Examples:"
echo " $(basename $0) wlan0 eth0 MyAccessPoint MyPassPhrase"
@@ -52,6 +54,7 @@ usage() {
echo " $(basename $0) wlan0 wlan0 MyAccessPoint MyPassPhrase"
echo " $(basename $0) -n wlan0 MyAccessPoint MyPassPhrase"
echo " $(basename $0) -m bridge wlan0 eth0 MyAccessPoint MyPassPhrase"
+ echo " $(basename $0) -m bridge wlan0 br0 MyAccessPoint MyPassPhrase"
echo " $(basename $0) --driver rtl871xdrv wlan0 eth0 MyAccessPoint MyPassPhrase"
}
@@ -88,6 +91,10 @@ is_wifi_interface() {
return 1
}
+is_bridge_interface() {
+ brctl show | cut -f1 | grep -E "^$1\$" > /dev/null 2>&1
+}
+
get_phy_device() {
for x in /sys/class/ieee80211/*; do
[[ ! -d "$x" ]] && continue
@@ -160,9 +167,8 @@ get_macaddr() {
get_avail_bridge() {
for i in {0..100}; do
- curr_bridge=$(brctl show | grep "br$i" | cut -s -f1)
- if [[ -z $curr_bridge ]]; then
- echo "br$i"
+ if ! is_bridge_interface "br${i}"; then
+ echo "br${i}"
return
fi
done
@@ -177,7 +183,6 @@ get_new_macaddr() {
echo $NEWMAC
}
-ADDED_UNMANAGED=0
NETWORKMANAGER_CONF=/etc/NetworkManager/NetworkManager.conf
NM_OLDER_VERSION=1
@@ -323,6 +328,8 @@ BRIDGE_IFACE=
OLD_IP_FORWARD=
OLD_BRIDGE_IPTABLES=
OLD_MACADDR=
+IP_ADDRS=
+ROUTE_ADDRS=
cleanup() {
trap "" SIGINT
@@ -345,19 +352,39 @@ cleanup() {
iptables -D FORWARD -i ${INTERNET_IFACE} -d ${GATEWAY%.*}.0/24 -j ACCEPT > /dev/null 2>&1
[[ -n $OLD_IP_FORWARD ]] && echo $OLD_IP_FORWARD > /proc/sys/net/ipv4/ip_forward
elif [[ "$SHARE_METHOD" == "bridge" ]]; then
- ip route show dev $BRIDGE_IFACE | grep -v -E '^default' | while read x; do
- ip route del $x dev $BRIDGE_IFACE
- ip route add $x dev $INTERNET_IFACE
- done
-
- ip route show dev $BRIDGE_IFACE | grep -E '^default' | while read x; do
- ip route del $x dev $BRIDGE_IFACE
- ip route add $x dev $INTERNET_IFACE
- done
+ if [[ -n $OLD_BRIDGE_IPTABLES ]]; then
+ echo $OLD_BRIDGE_IPTABLES > /proc/sys/net/bridge/bridge-nf-call-iptables
+ fi
- ip link set down $BRIDGE_IFACE
- brctl delbr $BRIDGE_IFACE
- [[ -n $OLD_BRIDGE_IPTABLES ]] && echo $OLD_BRIDGE_IPTABLES > /proc/sys/net/bridge/bridge-nf-call-iptables
+ if ! is_bridge_interface $INTERNET_IFACE; then
+ ip link set down $BRIDGE_IFACE
+ brctl delbr $BRIDGE_IFACE
+ ip addr flush $INTERNET_IFACE
+ ip link set dev $INTERNET_IFACE up
+
+ for x in "${IP_ADDRS[@]}"; do
+ x="${x/inet/}"
+ x="${x/secondary/}"
+ x="${x/dynamic/}"
+ x=$(echo $x | sed 's/\([0-9]\)sec/\1/g')
+ x="${x/${INTERNET_IFACE}/}"
+ ip addr add $x dev $INTERNET_IFACE
+ done
+
+ ip route flush dev $INTERNET_IFACE
+
+ for x in "${ROUTE_ADDRS[@]}"; do
+ [[ "$x" == default* ]] && continue
+ ip route add $x dev $INTERNET_IFACE
+ done
+
+ for x in "${ROUTE_ADDRS[@]}"; do
+ [[ "$x" != default* ]] && continue
+ ip route add $x dev $INTERNET_IFACE
+ done
+
+ networkmanager_rm_unmanaged_if_needed $INTERNET_IFACE
+ fi
fi
fi
@@ -501,17 +528,6 @@ if [[ "$SHARE_METHOD" != "nat" && "$SHARE_METHOD" != "bridge" && "$SHARE_METHOD"
exit 1
fi
-if [[ "$SHARE_METHOD" == "bridge" ]]; then
- OLD_BRIDGE_IPTABLES=$(cat /proc/sys/net/bridge/bridge-nf-call-iptables)
- BRIDGE_IFACE=$(get_avail_bridge)
- if [[ -z $BRIDGE_IFACE ]]; then
- echo "ERROR: No availabe bridges < br100" >&2
- exit 1
- fi
-elif [[ "$SHARE_METHOD" == "nat" ]]; then
- OLD_IP_FORWARD=$(cat /proc/sys/net/ipv4/ip_forward)
-fi
-
if [[ "$SHARE_METHOD" != "none" ]]; then
MIN_REQUIRED_ARGS=2
else
@@ -562,6 +578,23 @@ else
fi
fi
+if [[ "$SHARE_METHOD" == "bridge" ]]; then
+ OLD_BRIDGE_IPTABLES=$(cat /proc/sys/net/bridge/bridge-nf-call-iptables)
+
+ if is_bridge_interface $INTERNET_IFACE; then
+ BRIDGE_IFACE=$INTERNET_IFACE
+ else
+ BRIDGE_IFACE=$(get_avail_bridge)
+ fi
+
+ if [[ -z $BRIDGE_IFACE ]]; then
+ echo "ERROR: No availabe bridges < br100" >&2
+ exit 1
+ fi
+elif [[ "$SHARE_METHOD" == "nat" ]]; then
+ OLD_IP_FORWARD=$(cat /proc/sys/net/ipv4/ip_forward)
+fi
+
if [[ $NO_VIRT -eq 1 && "$WIFI_IFACE" == "$INTERNET_IFACE" ]]; then
echo -n "ERROR: You can not share your connection from the same" >&2
echo " interface if you are using --no-virt option." >&2
@@ -693,48 +726,65 @@ if [[ "$SHARE_METHOD" != "none" ]]; then
elif [[ "$SHARE_METHOD" == "bridge" ]]; then
# disable iptables rules for bridged interfaces
echo 0 > /proc/sys/net/bridge/bridge-nf-call-iptables || die
- # create and initialize bridged interface
- brctl addbr ${BRIDGE_IFACE} || die
- brctl addif ${BRIDGE_IFACE} ${INTERNET_IFACE} || die
# to initialize the bridge interface correctly we need to do the following:
#
- # 1) duplicate the IPs of INTERNET_IFACE to BRIDGE_IFACE
- # 2) duplicate routing table of INTERNET_IFACE to BRIDGE_IFACE
- # 3) delete routing table of INTERNET_IFACE
- # NOTE: we don't need to delete the IPs of INTERNET_IFACE
+ # 1) save the IPs and route table of INTERNET_IFACE
+ # 2) if NetworkManager is running set INTERNET_IFACE as unmanaged
+ # 3) create BRIDGE_IFACE and add INTERNET_IFACE to it
+ # 4) set the previously saved IPs and route table to BRIDGE_IFACE
#
# we need the above because BRIDGE_IFACE is the master interface from now on
# and it must know where is connected, otherwise connection is lost.
- ip link set dev ${BRIDGE_IFACE} up || die
+ if ! is_bridge_interface $INTERNET_IFACE; then
+ echo -n "Create a bridge interface... "
+ OLD_IFS="$IFS"
+ IFS=$'\n'
- ip addr show $INTERNET_IFACE | grep -E '[[:blank:]]+inet ' | while read x; do
- IPADDR=$(echo $x | sed 's/inet \([^ ]*\).*/\1/')
- BRDADDR=
- if [[ $x == *\ brd\ * ]]; then
- BRDADDR=$(echo $x | sed 's/.* brd \([^ ]*\).*/\1/')
- fi
- if [[ -n "$BRDADDR" ]]; then
- ip addr add $IPADDR broadcast $BRDADDR dev $BRIDGE_IFACE || die
- else
- ip addr add $IPADDR dev $BRIDGE_IFACE || die
+ IP_ADDRS=( $(ip addr show $INTERNET_IFACE | grep -A 1 -E 'inet[[:blank:]]' | paste - -) )
+ ROUTE_ADDRS=( $(ip route show dev $INTERNET_IFACE) )
+
+ IFS="$OLD_IFS"
+
+ if networkmanager_is_running; then
+ networkmanager_add_unmanaged $INTERNET_IFACE
+ networkmanager_wait_until_unmanaged $INTERNET_IFACE
fi
- done
- # remove any existing entries that were added from 'ip addr add'
- ip route flush dev $BRIDGE_IFACE || die
+ brctl addbr $BRIDGE_IFACE || die
+ brctl setfd $BRIDGE_IFACE 0
+ brctl addif $BRIDGE_IFACE $INTERNET_IFACE || die
+ ip link set dev $BRIDGE_IFACE up || die
+ ip link set dev $INTERNET_IFACE up || die
+
+ ip addr flush $INTERNET_IFACE
+ for x in "${IP_ADDRS[@]}"; do
+ x="${x/inet/}"
+ x="${x/secondary/}"
+ x="${x/dynamic/}"
+ x=$(echo $x | sed 's/\([0-9]\)sec/\1/g')
+ x="${x/${INTERNET_IFACE}/}"
+ ip addr add $x dev $BRIDGE_IFACE || die
+ done
- # we must first add the entries that specify the subnets and then the
- # gateway entry, otherwise 'ip addr add' will return an error
- ip route show dev $INTERNET_IFACE | grep -v -E '^default' | while read x; do
- ip route del $x dev $INTERNET_IFACE || die
- ip route add $x dev $BRIDGE_IFACE || die
- done
+ # remove any existing entries that were added from 'ip addr add'
+ ip route flush dev $INTERNET_IFACE
+ ip route flush dev $BRIDGE_IFACE
- ip route show dev $INTERNET_IFACE | grep -E '^default' | while read x; do
- ip route del $x dev $INTERNET_IFACE || die
- ip route add $x dev $BRIDGE_IFACE || die
- done
+ # we must first add the entries that specify the subnets and then the
+ # gateway entry, otherwise 'ip addr add' will return an error
+ for x in "${ROUTE_ADDRS[@]}"; do
+ [[ "$x" == default* ]] && continue
+ ip route add $x dev $BRIDGE_IFACE || die
+ done
+
+ for x in "${ROUTE_ADDRS[@]}"; do
+ [[ "$x" != default* ]] && continue
+ ip route add $x dev $BRIDGE_IFACE || die
+ done
+
+ echo "$BRIDGE_IFACE created."
+ fi
fi
else
echo "No Internet sharing"