connect.sh 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  1. #!/bin/sh
  2. #
  3. # Network connection script
  4. #
  5. # Copyright (c) 2012 Michael Buesch <m@bues.ch>
  6. # Licensed under GNU GPL version 2 or later.
  7. #
  8. scriptdir="$(dirname "$0")"
  9. [ "$(echo "$scriptdir" | cut -c1)" = '/' ] || scriptdir="$PWD/$scriptdir"
  10. vpndir="$scriptdir/vpn"
  11. dundir="$scriptdir/dun"
  12. debug()
  13. {
  14. [ -n "$opt_debug" ] && echo "$*"
  15. }
  16. info()
  17. {
  18. echo "$*"
  19. }
  20. info_n()
  21. {
  22. echo -n "$*"
  23. }
  24. warn()
  25. {
  26. echo "Warning: $*" >&2
  27. }
  28. error()
  29. {
  30. echo "ERROR: $*" >&2
  31. }
  32. die()
  33. {
  34. error "$*"
  35. cleanup_handler
  36. exit 1
  37. }
  38. # $1=program_name
  39. have_program()
  40. {
  41. which "$1" >/dev/null 2>&1
  42. }
  43. # $1=option
  44. check_bool_opt()
  45. {
  46. local option="$1"
  47. [ "$option" = "1" -o \
  48. "$option" = "on" -o \
  49. "$option" = "true" ]
  50. }
  51. rfcomm()
  52. {
  53. # Force rfcomm into line buffered stdout
  54. stdbuf -oL rfcomm "$@"
  55. }
  56. # Start bluetooth-agent.
  57. # Returns the PID of bluetooth-agent
  58. # $1=passkey (optional. Defaults to 1234)
  59. bluetooth_agent_start()
  60. {
  61. local passkey="$1"
  62. local pid=
  63. [ -n "$passkey" ] || passkey="1234"
  64. info "Starting bluetooth agent with passkey '$passkey'"
  65. bluetoothctl << EOF
  66. power on
  67. discoverable off
  68. pairable on
  69. agent on
  70. default-agent
  71. EOF
  72. # bluetooth-agent "$passkey" &
  73. pid=$!
  74. sleep 1
  75. return $pid
  76. }
  77. # $1=apn
  78. make_chatscript()
  79. {
  80. local apn="$1"
  81. cat << EOF
  82. TIMEOUT 120
  83. ABORT 'BUSY'
  84. ABORT 'ERROR'
  85. ABORT 'NO CARRIER'
  86. '' 'ATE1'
  87. OK AT+CGDCONT=1,"IP","${apn}"
  88. OK ATD*99#
  89. CONNECT \\d\\c
  90. EOF
  91. }
  92. random_byte()
  93. {
  94. hexdump -n1 -e'/1 "%u"' /dev/urandom
  95. }
  96. random_hex_byte()
  97. {
  98. hexdump -n1 -e'/1 "%02X"' /dev/urandom
  99. }
  100. random_word()
  101. {
  102. hexdump -n2 -e'/2 "%u"' /dev/urandom
  103. }
  104. random_macaddr()
  105. {
  106. # Clear local-admin and mcast bits
  107. echo -n "$(printf '%02X' $(($(random_byte) & ~3))):"
  108. echo -n "$(random_hex_byte):$(random_hex_byte):"
  109. echo -n "$(random_hex_byte):$(random_hex_byte):"
  110. echo -n "$(random_hex_byte)"
  111. }
  112. get_default_route_ipaddr()
  113. {
  114. ip route show | grep '^default' | awk '{print $3;}'
  115. }
  116. get_default_route_if()
  117. {
  118. ip route show | grep '^default' | awk '{print $5;}'
  119. }
  120. get_unused_tun_device()
  121. {
  122. for i in $(seq 0 99); do
  123. local tun="tun$i"
  124. ip link show dev "$tun" >/dev/null 2>&1 || {
  125. echo -n "$tun"
  126. return
  127. }
  128. done
  129. }
  130. # $1=basename
  131. get_unused_dev_node()
  132. {
  133. local base="$1"
  134. for i in $(seq 0 99); do
  135. local dev="/dev/$base$i"
  136. [ -e "$dev" ] || {
  137. echo -n "$dev"
  138. return
  139. }
  140. done
  141. }
  142. string_is_false()
  143. {
  144. local str="$1"
  145. [ -z "$str" -o "$str" = "0" -o \
  146. "$str" = "off" -o "$str" = "no" -o \
  147. "$str" = "false" ]
  148. }
  149. # $1=pid
  150. pid_is_alife()
  151. {
  152. local pid="$1"
  153. [ -n "$pid" -a -d "/proc/$pid" ]
  154. }
  155. # $1=type, $2=name, $3=PID, $4=ready_callback, $5=timeout_decisec
  156. wait_pid_alife_and_callback()
  157. {
  158. local type="$1"
  159. local name="$2"
  160. local pid="$3"
  161. local ready_callback="$4"
  162. local timeout_decisec="$5"
  163. info_n "Waiting for '$name' '$type'..."
  164. local i=0
  165. while true; do
  166. sleep 0.1
  167. pid_is_alife "$pid" || {
  168. cat "$logfile"
  169. die "'$name' '$type' died"
  170. }
  171. eval "$ready_callback" && break
  172. i="$(expr $i + 1)"
  173. [ $i -ge $timeout_decisec ] && {
  174. cat "$logfile"
  175. die "'$name' '$type' timeout"
  176. }
  177. [ "$(expr $i % 10)" -eq 0 ] && info_n "."
  178. done
  179. info ""
  180. }
  181. # $1=type, $2=name, $3=PID, $4=dead_callback, $5=timeout_decisec
  182. wait_pid_dead_or_callback()
  183. {
  184. local type="$1"
  185. local name="$2"
  186. local pid="$3"
  187. local dead_callback="$4"
  188. local timeout_decisec="$5"
  189. info_n "Waiting for '$name' '$type' (pid $pid) to die..."
  190. local i=0
  191. while true; do
  192. sleep 0.1
  193. pid_is_alife "$pid" || break
  194. eval "$dead_callback" && break
  195. i="$(expr $i + 1)"
  196. [ $i -ge $timeout_decisec ] && {
  197. cat "$logfile"
  198. die "'$name' '$type' timeout"
  199. }
  200. [ "$(expr $i % 10)" -eq 0 ] && info_n "."
  201. done
  202. info ""
  203. }
  204. # $1=type, $2=name, $3=PID, $4=logfile, $5=log_regex, $6=timeout_decisec
  205. wait_pid_alife_and_logmsg()
  206. {
  207. local type="$1"
  208. local name="$2"
  209. local pid="$3"
  210. local logfile="$4"
  211. local log_regex="$5"
  212. local timeout_decisec="$6"
  213. ready_callback() {
  214. grep -qe "$log_regex" "$logfile"
  215. }
  216. wait_pid_alife_and_callback "$type" "$name" "$pid" \
  217. ready_callback "$timeout_decisec"
  218. }
  219. # $1=type, $2=name, $3=PID, $4=logfile, $5=log_regex, $6=timeout_decisec
  220. wait_pid_dead_or_logmsg()
  221. {
  222. local type="$1"
  223. local name="$2"
  224. local pid="$3"
  225. local logfile="$4"
  226. local log_regex="$5"
  227. local timeout_decisec="$6"
  228. dead_callback() {
  229. grep -qe "$log_regex" "$logfile"
  230. }
  231. wait_pid_dead_or_callback "$type" "$name" "$pid" \
  232. dead_callback "$timeout_decisec"
  233. }
  234. # $1=hcidev
  235. hci_dev_up()
  236. {
  237. local hcidev="$1"
  238. hciconfig "$hcidev" up ||\
  239. die "Failed to bring bluetooth device '$hcidev' up"
  240. }
  241. # $1=hcidev
  242. hci_dev_down()
  243. {
  244. local hcidev="$1"
  245. hciconfig "$hcidev" down ||\
  246. warn "Failed to bring bluetooth device '$hcidev' down"
  247. }
  248. # $1=name, $2=PID, $3=logfile
  249. openvpn_wait_connect()
  250. {
  251. wait_pid_alife_and_logmsg "OpenVPN" "$1" "$2" "$3" \
  252. "Initialization Sequence Completed" 900
  253. }
  254. # $1=name, $2=PID, $3=logfile
  255. openvpn_wait_disconnect()
  256. {
  257. wait_pid_dead_or_logmsg "OpenVPN" "$1" "$2" "$3" \
  258. "received, process exiting" 300
  259. }
  260. # $1=name, $2=PID, $3=logfile
  261. rfcomm_wait_connect()
  262. {
  263. wait_pid_alife_and_logmsg "rfcomm" "$1" "$2" "$3" \
  264. "Connected /dev/rfcomm" 600
  265. sleep 0.5
  266. }
  267. # $1=name, $2=PID, $3=logfile
  268. rfcomm_wait_disconnect()
  269. {
  270. wait_pid_dead_or_logmsg "rfcomm" "$1" "$2" "$3" \
  271. "Disconnected" 300
  272. }
  273. # $1=name, $2=PID, $3=logfile
  274. pppd_wait_connect()
  275. {
  276. wait_pid_alife_and_logmsg "pppd" "$1" "$2" "$3" \
  277. "local IP address" 1000
  278. sleep 0.5
  279. }
  280. # $1=name, $2=PID, $3=logfile
  281. pppd_wait_disconnect()
  282. {
  283. wait_pid_dead_or_logmsg "pppd" "$1" "$2" "$3" \
  284. "Connection terminated" 300
  285. }
  286. # $1=pid
  287. kill_pid()
  288. {
  289. local pid="$1"
  290. pid_is_alife "$pid" || return
  291. kill -TERM "$pid" >/dev/null 2>&1
  292. }
  293. # $1=type, $2=name, $3=PID, $4=wait_callback, $5=logfile
  294. generic_kill_with_logfile()
  295. {
  296. local type="$1"
  297. local name="$2"
  298. local pid="$3"
  299. local wait_callback="$4"
  300. local logfile="$5"
  301. [ -z "$pid" ] && return
  302. debug "Killing '$name' '$type' daemon..."
  303. kill_pid "$pid"
  304. eval "$wait_callback"
  305. truncate -s 0 "$logfile" || \
  306. die "Failed to truncate '$type' '$name' logfile"
  307. }
  308. # $1=name, $2=PID, $3=logfile
  309. openvpn_kill()
  310. {
  311. local name="$1"
  312. local pid="$2"
  313. local logfile="$3"
  314. wait_callback() {
  315. openvpn_wait_disconnect "$name" "$pid" "$logfile"
  316. }
  317. generic_kill_with_logfile "OpenVPN" "$name" "$pid" \
  318. wait_callback "$logfile"
  319. }
  320. # $1=name, $2=PID
  321. bluetooth_agent_kill()
  322. {
  323. local name="$1"
  324. local pid="$2"
  325. debug "Killing '$name' bluetooth-agent..."
  326. kill_pid "$pid"
  327. }
  328. # $1=name, $2=PID, $3=logfile
  329. rfcomm_kill()
  330. {
  331. local name="$1"
  332. local pid="$2"
  333. local logfile="$3"
  334. wait_callback() {
  335. rfcomm_wait_disconnect "$name" "$pid" "$logfile"
  336. }
  337. generic_kill_with_logfile "rfcomm" "$name" "$pid" \
  338. wait_callback "$logfile"
  339. }
  340. # $1=name, $2=PID, $3=logfile
  341. pppd_kill()
  342. {
  343. local name="$1"
  344. local pid="$2"
  345. local logfile="$3"
  346. wait_callback() {
  347. pppd_wait_disconnect "$name" "$pid" "$logfile"
  348. }
  349. generic_kill_with_logfile "pppd" "$name" "$pid" \
  350. wait_callback "$logfile"
  351. }
  352. wlan_macaddr_spoof()
  353. {
  354. [ "$opt_wlanif" = "none" ] && return
  355. [ -n "$opt_macspoof" ] && string_is_false "$opt_macspoof" && return
  356. local macaddr=
  357. if [ -f "$opt_macspoof" ]; then
  358. [ -r "$opt_macspoof" ] || \
  359. die "Can't read MAC-spoof file '$opt_macspoof'"
  360. local count="$(wc -w "$opt_macspoof" | awk '{print $1;}')"
  361. [ -z "$count" -o "$count" = "0" ] && \
  362. die "No MAC-addresses in '$opt_macspoof'"
  363. local picked="$(($(random_word) % $count + 1))"
  364. macaddr="$(cat "$opt_macspoof" | tr '\n' ' ' | awk '{print $'$picked';}')"
  365. elif [ -n "$opt_macspoof" ]; then
  366. macaddr="$opt_macspoof"
  367. else
  368. macaddr="$(random_macaddr)"
  369. fi
  370. [ -n "$macaddr" ] || die "Failed to pick a MAC-address from '$opt_macspoof'"
  371. info "Spoofing MAC address '$macaddr'"
  372. ip link set down dev "$opt_wlanif" || \
  373. die "Failed to bring '$opt_wlanif' down"
  374. ip link set address "$macaddr" dev "$opt_wlanif" || \
  375. die "Failed to set MAC address '$macaddr' on '$opt_wlanif'"
  376. }
  377. wlan_connect()
  378. {
  379. [ "$opt_wlanif" = "none" -o "$opt_wlanif" = "-" ] && return
  380. debug "Shutting down system wpa_supplicant..."
  381. (
  382. local wpa_funcs="/etc/wpa_supplicant/functions.sh"
  383. [ -f "$wpa_funcs" ] && {
  384. . "$wpa_funcs"
  385. kill_wpa_cli
  386. kill_wpa_supplicant
  387. }
  388. )
  389. pkill wpa_supplicant
  390. wlan_macaddr_spoof
  391. info "Connecting WLAN..."
  392. wpa_supplicant_pidfile="/var/run/wpa_supplicant-connect-$opt_wlanif.pid"
  393. wpa_supplicant -B -Dnl80211 \
  394. -i "$opt_wlanif" -c "$opt_suppconf" \
  395. -P "$wpa_supplicant_pidfile"
  396. ready_callback() {
  397. wpa_cli -i "$opt_wlanif" status | \
  398. grep -qe 'wpa_state=COMPLETED'
  399. }
  400. sleep 0.5
  401. wait_pid_alife_and_callback "WLAN" "$opt_wlanif" \
  402. "$(cat "$wpa_supplicant_pidfile")" ready_callback 600
  403. local ps="off"
  404. check_bool_opt "$opt_powersave" && ps="on"
  405. iw dev "$opt_wlanif" set power_save "$ps" || \
  406. warn "Failed to turn power saving on '$opt_wlanif' $ps"
  407. }
  408. wlan_disconnect()
  409. {
  410. [ "$opt_wlanif" = "none" -o "$opt_wlanif" = "-" ] && return
  411. debug "Disconnecting WLAN..."
  412. [ -z "$wpa_supplicant_pidfile" ] && return
  413. local pid="$(cat "$wpa_supplicant_pidfile")"
  414. kill_pid "$pid"
  415. wpa_supplicant_pidfile=
  416. dead_callback() {
  417. ! wpa_cli -i "$opt_wlanif" status >/dev/null 2>&1
  418. }
  419. wait_pid_dead_or_callback "WLAN" "$opt_wlanif" \
  420. "$pid" dead_callback 300
  421. }
  422. dhcp_connect()
  423. {
  424. [ -n "$opt_nodhcp" ] && return
  425. info "Configuring DHCP..."
  426. dhclient_pidfile="/var/run/dhclient-$opt_wlanif.pid"
  427. dhclient -v -4 -pf "$dhclient_pidfile" "$opt_wlanif" 2>&1 |\
  428. grep -Ee '(^DHCP)|(^bound to)'
  429. }
  430. dhcp_disconnect()
  431. {
  432. [ -n "$opt_nodhcp" ] && return
  433. debug "Killing DHCP..."
  434. [ -z "$dhclient_pidfile" ] && return
  435. kill_pid "$(cat "$dhclient_pidfile")"
  436. dhclient_pidfile=
  437. }
  438. resolver_adjust()
  439. {
  440. if [ -n "$opt_resolver" ]; then
  441. # Static resolver specified.
  442. have_program resolvconf && {
  443. resolvconf --updates-are-enabled && {
  444. info "Disabling resolvconf updates"
  445. resolvconf --disable-updates
  446. }
  447. }
  448. debug "Setting resolver to '$opt_resolver'..."
  449. echo "nameserver $opt_resolver" > /etc/resolv.conf ||\
  450. die "Failed to set resolver to '$opt_resolver'"
  451. else
  452. # No static resolver specified.
  453. have_program resolvconf && {
  454. resolvconf --updates-are-enabled || {
  455. info "Enabling resolvconf updates"
  456. resolvconf --enable-updates
  457. }
  458. }
  459. fi
  460. }
  461. source_config() # $1=basedir, $2=script_name
  462. {
  463. local basedir="$1"
  464. local name="$2"
  465. local script="$scriptdir/$basedir/$name.sh"
  466. [ -f "$script" ] || \
  467. die "No config for '$basedir/$name'"
  468. . "$script" || \
  469. die "Config '$basedir/$name' returned an error."
  470. }
  471. vpn_connect()
  472. {
  473. [ -z "$opt_vpns" ] && return
  474. for vpn_name in $opt_vpns; do
  475. info "Connecting VPN '$vpn_name'..."
  476. # Define defaults
  477. vpn_prepare() { true; }
  478. vpn_start() { die "No vpn_start() callback in '$vpn_name'"; }
  479. vpn_routing_setup() { true; }
  480. # Source the config
  481. source_config vpn "$vpn_name"
  482. # Perform the configuration
  483. vpn_prepare
  484. vpn_start
  485. vpn_routing_setup
  486. done
  487. }
  488. vpn_disconnect()
  489. {
  490. [ -z "$opt_vpns" ] && return
  491. for vpn_name in $(echo $opt_vpns | tac -s' '); do
  492. debug "Disconnecting VPN '$vpn_name'..."
  493. # Define defaults
  494. vpn_stop() { true; }
  495. vpn_routing_cleanup() { true; }
  496. vpn_destroy() { true; }
  497. # Source the config
  498. source_config vpn "$vpn_name"
  499. # Perform cleanup
  500. vpn_routing_cleanup
  501. vpn_stop
  502. vpn_destroy
  503. done
  504. }
  505. dun_connect()
  506. {
  507. [ -z "$opt_duns" ] && return
  508. for dun_name in $opt_duns; do
  509. info "Connecting DUN '$dun_name'..."
  510. # Define defaults
  511. dun_prepare() { true; }
  512. dun_start() { die "No dun_start() callback in '$dun_name'"; }
  513. dun_routing_setup() { true; }
  514. # Source the config
  515. source_config dun "$dun_name"
  516. # Perform the configuration
  517. dun_prepare
  518. dun_start
  519. dun_routing_setup
  520. done
  521. }
  522. dun_disconnect()
  523. {
  524. [ -z "$opt_duns" ] && return
  525. for dun_name in $(echo $opt_duns | tac -s' '); do
  526. debug "Disconnecting DUN '$dun_name'..."
  527. # Define defaults
  528. dun_stop() { true; }
  529. dun_routing_cleanup() { true; }
  530. dun_destroy() { true; }
  531. # Source the config
  532. source_config dun "$dun_name"
  533. # Perform cleanup
  534. dun_routing_cleanup
  535. dun_stop
  536. dun_destroy
  537. done
  538. }
  539. stop_nm()
  540. {
  541. systemctl status network-manager.service |\
  542. grep -qe 'Active: active (running)' && {
  543. debug "Stopping network-manager..."
  544. systemctl stop network-manager.service
  545. sleep 1
  546. }
  547. }
  548. wait_loop()
  549. {
  550. info "Connections up and running. [Press ^C to abort]"
  551. # Wait for signal
  552. while true; do
  553. sleep 60
  554. #TODO check connection
  555. done
  556. }
  557. cleanup_handler()
  558. {
  559. debug "Cleanup..."
  560. vpn_disconnect
  561. dhcp_disconnect
  562. wlan_disconnect
  563. dun_disconnect
  564. exit 0
  565. }
  566. usage()
  567. {
  568. echo "connect.sh [OPTIONS]"
  569. echo
  570. echo "Options:"
  571. echo " -w|--wlanif IF WLAN interface (default wlan0)"
  572. echo " -m|--macspoof MAC/FILE/no Use MAC address or FILE."
  573. echo " -p|--powersave on/off Turn WLAN power-saving on/off."
  574. echo " -S|--suppconf FILE WPA-supplicant config"
  575. echo " -D|--nodhcp Don't configure DHCP"
  576. echo " -R|--resolver IP Resolver IP address (default dhcp or 127.0.0.1)"
  577. echo " -u|--dun NAME Connect Dial Up Network NAME"
  578. echo " -V|--vpn NAME Connect to VPN"
  579. echo " -P|--httpproxy IP:PORT[:AUTH:PASS] Use HTTP proxy"
  580. echo " -d|--debug Enable debug messages"
  581. echo " -h|--help Show this help text"
  582. }
  583. parse_args()
  584. {
  585. while [ $# -ne 0 ]; do
  586. case "$1" in
  587. -S|--suppconf)
  588. shift
  589. local path="$1"
  590. [ -n "$path" ] || die "-S|--suppconf needs an argument"
  591. opt_suppconf="$path"
  592. ;;
  593. -w|--wlanif)
  594. shift
  595. local name="$1"
  596. [ -n "$name" ] || die "-w|--wlanif needs an argument"
  597. opt_wlanif="$name"
  598. ;;
  599. -m|--macspoof)
  600. shift
  601. local path="$1"
  602. [ -n "$path" ] || die "-m|--macspoof needs an argument"
  603. opt_macspoof="$path"
  604. ;;
  605. -p|--powersave)
  606. shift
  607. local ps="$1"
  608. [ -n "$ps" ] || die "-p|--powersave needs an argument"
  609. opt_powersave="$ps"
  610. ;;
  611. -R|--resolver)
  612. shift
  613. local res="$1"
  614. [ -n "$res" ] || die "-R|--resolver needs an argument"
  615. opt_resolver="$res"
  616. ;;
  617. -u|--dun)
  618. shift
  619. local name="$1"
  620. [ -n "$name" ] || die "-u|--dun needs an argument"
  621. opt_duns="$opt_duns $name"
  622. ;;
  623. -V|--vpn)
  624. shift
  625. local name="$1"
  626. [ -n "$name" ] || die "-V|--vpn needs an argument"
  627. opt_vpns="$opt_vpns $name"
  628. ;;
  629. -P|--httpproxy)
  630. shift
  631. local conf="$1"
  632. [ -n "$conf" ] || die "-P|--httpproxy needs an argument"
  633. opt_httpproxy_host="$(echo "$conf" | cut -d':' -f1)"
  634. opt_httpproxy_port="$(echo "$conf" | cut -d':' -f2)"
  635. opt_httpproxy_auth="$(echo "$conf" | cut -d':' -f3)"
  636. opt_httpproxy_pass="$(echo "$conf" | cut -d':' -f4)"
  637. [ -n "$opt_httpproxy_host" -a \
  638. -n "$opt_httpproxy_port" ] || \
  639. die "-P|--httpproxy needs HOST:PORT"
  640. ;;
  641. -D|--nodhcp)
  642. opt_nodhcp=1
  643. ;;
  644. -d|--debug)
  645. opt_debug=1
  646. ;;
  647. -h|--help)
  648. usage
  649. exit 0
  650. ;;
  651. *)
  652. die "Unknown option: $1"
  653. ;;
  654. esac
  655. shift
  656. done
  657. }
  658. opt_debug=
  659. opt_vpns=
  660. opt_wlanif="wlan0"
  661. opt_macspoof=
  662. opt_powersave="on"
  663. opt_suppconf="/etc/wpa_supplicant/wpa_supplicant.conf"
  664. opt_duns=
  665. opt_nodhcp=
  666. opt_resolver=
  667. opt_httpproxy_host=
  668. opt_httpproxy_port=
  669. opt_httpproxy_auth=
  670. opt_httpproxy_pass=
  671. parse_args "$@"
  672. [ -n "$opt_duns" ] && {
  673. # DUN implies no WLAN and no DHCP
  674. opt_wlanif=none
  675. opt_nodhcp=1
  676. }
  677. [ -z "$opt_resolver" -a -n "$opt_nodhcp" ] && {
  678. # Default resolver to localhost
  679. opt_resolver="127.0.0.1"
  680. }
  681. TRAPPED_SIGS="INT TERM"
  682. trap cleanup_handler $TRAPPED_SIGS
  683. while true; do
  684. stop_nm
  685. wlan_connect
  686. dun_connect
  687. resolver_adjust
  688. dhcp_connect
  689. vpn_connect
  690. wait_loop
  691. trap true $TRAPPED_SIGS
  692. cleanup_handler
  693. trap cleanup_handler $TRAPPED_SIGS
  694. done
  695. exit 1