mirror of
https://github.com/bolucat/Archive.git
synced 2025-12-24 13:28:37 +08:00
Update On Fri Oct 24 20:39:48 CEST 2025
This commit is contained in:
1
.github/update.log
vendored
1
.github/update.log
vendored
@@ -1160,3 +1160,4 @@ Update On Mon Oct 20 20:40:25 CEST 2025
|
||||
Update On Tue Oct 21 20:38:48 CEST 2025
|
||||
Update On Wed Oct 22 20:43:37 CEST 2025
|
||||
Update On Thu Oct 23 20:39:01 CEST 2025
|
||||
Update On Fri Oct 24 20:39:40 CEST 2025
|
||||
|
||||
@@ -24,7 +24,7 @@ require (
|
||||
github.com/metacubex/fswatch v0.1.1
|
||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759
|
||||
github.com/metacubex/kcp-go v0.0.0-20251007183319-0df1aec1639a
|
||||
github.com/metacubex/quic-go v0.55.1-0.20251004050223-450bd9e32033
|
||||
github.com/metacubex/quic-go v0.55.1-0.20251024060151-bd465f127128
|
||||
github.com/metacubex/randv2 v0.2.0
|
||||
github.com/metacubex/restls-client-go v0.1.7
|
||||
github.com/metacubex/sing v0.5.6
|
||||
@@ -37,7 +37,7 @@ require (
|
||||
github.com/metacubex/sing-vmess v0.2.4
|
||||
github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f
|
||||
github.com/metacubex/smux v0.0.0-20250922175018-15c9a6a78719
|
||||
github.com/metacubex/tfo-go v0.0.0-20250921095601-b102db4216c0
|
||||
github.com/metacubex/tfo-go v0.0.0-20251024101424-368b42b59148
|
||||
github.com/metacubex/utls v1.8.3
|
||||
github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f
|
||||
github.com/miekg/dns v1.1.63 // lastest version compatible with golang1.20
|
||||
|
||||
@@ -112,8 +112,8 @@ github.com/metacubex/kcp-go v0.0.0-20251007183319-0df1aec1639a h1:5vdk2pI71itLBT
|
||||
github.com/metacubex/kcp-go v0.0.0-20251007183319-0df1aec1639a/go.mod h1:HIJZW4QMhbBqXuqC1ly6Hn0TEYT2SzRw58ns1yGhXTs=
|
||||
github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 h1:1Qpuy+sU3DmyX9HwI+CrBT/oLNJngvBorR2RbajJcqo=
|
||||
github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793/go.mod h1:RjRNb4G52yAgfR+Oe/kp9G4PJJ97Fnj89eY1BFO3YyA=
|
||||
github.com/metacubex/quic-go v0.55.1-0.20251004050223-450bd9e32033 h1:LEzvR5AmHEatqE6IWgMBUJHnaiz9VJfZeDGOiHFuWZU=
|
||||
github.com/metacubex/quic-go v0.55.1-0.20251004050223-450bd9e32033/go.mod h1:1lktQFtCD17FZliVypbrDHwbsFSsmz2xz2TRXydvB5c=
|
||||
github.com/metacubex/quic-go v0.55.1-0.20251024060151-bd465f127128 h1:I1uvJl206/HbkzEAZpLgGkZgUveOZb+P+6oTUj7dN+o=
|
||||
github.com/metacubex/quic-go v0.55.1-0.20251024060151-bd465f127128/go.mod h1:1lktQFtCD17FZliVypbrDHwbsFSsmz2xz2TRXydvB5c=
|
||||
github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
|
||||
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
|
||||
github.com/metacubex/restls-client-go v0.1.7 h1:eCwiXCTQb5WJu9IlgYvDBA1OgrINv58dEe7hcN5H15k=
|
||||
@@ -139,8 +139,8 @@ github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f h1:Sr/DYK
|
||||
github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f/go.mod h1:jpAkVLPnCpGSfNyVmj6Cq4YbuZsFepm/Dc+9BAOcR80=
|
||||
github.com/metacubex/smux v0.0.0-20250922175018-15c9a6a78719 h1:T6qCCfolRDAVJKeaPW/mXwNLjnlo65AYN7WS2jrBNaM=
|
||||
github.com/metacubex/smux v0.0.0-20250922175018-15c9a6a78719/go.mod h1:4bPD8HWx9jPJ9aE4uadgyN7D1/Wz3KmPy+vale8sKLE=
|
||||
github.com/metacubex/tfo-go v0.0.0-20250921095601-b102db4216c0 h1:Ui+/2s5Qz0lSnDUBmEL12M5Oi/PzvFxGTNohm8ZcsmE=
|
||||
github.com/metacubex/tfo-go v0.0.0-20250921095601-b102db4216c0/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw=
|
||||
github.com/metacubex/tfo-go v0.0.0-20251024101424-368b42b59148 h1:Zd0QqciLIhv9MKbGKTPEgN8WUFsgQGA1WJBy6spEnVU=
|
||||
github.com/metacubex/tfo-go v0.0.0-20251024101424-368b42b59148/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw=
|
||||
github.com/metacubex/utls v1.8.3 h1:0m/yCxm3SK6kWve2lKiFb1pue1wHitJ8sQQD4Ikqde4=
|
||||
github.com/metacubex/utls v1.8.3/go.mod h1:kncGGVhFaoGn5M3pFe3SXhZCzsbCJayNOH4UEqTKTko=
|
||||
github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f h1:FGBPRb1zUabhPhDrlKEjQ9lgIwQ6cHL4x8M9lrERhbk=
|
||||
|
||||
@@ -21,7 +21,6 @@ func SetCongestionController(quicConn *quic.Conn, cc string, cwnd int) {
|
||||
case "cubic":
|
||||
quicConn.SetCongestionControl(
|
||||
congestion.NewCubicSender(
|
||||
congestion.DefaultClock{},
|
||||
congestion.GetInitialPacketSize(quicConn),
|
||||
false,
|
||||
),
|
||||
@@ -29,7 +28,6 @@ func SetCongestionController(quicConn *quic.Conn, cc string, cwnd int) {
|
||||
case "new_reno":
|
||||
quicConn.SetCongestionControl(
|
||||
congestion.NewCubicSender(
|
||||
congestion.DefaultClock{},
|
||||
congestion.GetInitialPacketSize(quicConn),
|
||||
true,
|
||||
),
|
||||
@@ -37,7 +35,6 @@ func SetCongestionController(quicConn *quic.Conn, cc string, cwnd int) {
|
||||
case "bbr_meta_v1":
|
||||
quicConn.SetCongestionControl(
|
||||
congestion.NewBBRSender(
|
||||
congestion.DefaultClock{},
|
||||
congestion.GetInitialPacketSize(quicConn),
|
||||
c.ByteCount(cwnd)*congestion.InitialMaxDatagramSize,
|
||||
congestion.DefaultBBRMaxCongestionWindow*congestion.InitialMaxDatagramSize,
|
||||
@@ -48,7 +45,6 @@ func SetCongestionController(quicConn *quic.Conn, cc string, cwnd int) {
|
||||
case "bbr":
|
||||
quicConn.SetCongestionControl(
|
||||
congestionv2.NewBbrSender(
|
||||
congestionv2.DefaultClock{},
|
||||
congestionv2.GetInitialPacketSize(quicConn),
|
||||
c.ByteCount(cwnd),
|
||||
),
|
||||
|
||||
@@ -101,7 +101,6 @@ const (
|
||||
|
||||
type bbrSender struct {
|
||||
mode bbrMode
|
||||
clock Clock
|
||||
rttStats congestion.RTTStatsProvider
|
||||
bytesInFlight congestion.ByteCount
|
||||
// return total bytes of unacked packets.
|
||||
@@ -232,14 +231,12 @@ type bbrSender struct {
|
||||
}
|
||||
|
||||
func NewBBRSender(
|
||||
clock Clock,
|
||||
initialMaxDatagramSize,
|
||||
initialCongestionWindow,
|
||||
initialMaxCongestionWindow congestion.ByteCount,
|
||||
) *bbrSender {
|
||||
b := &bbrSender{
|
||||
mode: STARTUP,
|
||||
clock: clock,
|
||||
sampler: NewBandwidthSampler(),
|
||||
maxBandwidth: NewWindowedFilter(int64(BandwidthWindowSize), MaxFilter),
|
||||
maxAckHeight: NewWindowedFilter(int64(BandwidthWindowSize), MaxFilter),
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
package congestion
|
||||
|
||||
import "time"
|
||||
|
||||
// A Clock returns the current time
|
||||
type Clock interface {
|
||||
Now() time.Time
|
||||
}
|
||||
|
||||
// DefaultClock implements the Clock interface using the Go stdlib clock.
|
||||
type DefaultClock struct{}
|
||||
|
||||
var _ Clock = DefaultClock{}
|
||||
|
||||
// Now gets the current time
|
||||
func (DefaultClock) Now() time.Time {
|
||||
return time.Now()
|
||||
}
|
||||
@@ -37,8 +37,6 @@ const betaLastMax float32 = 0.85
|
||||
|
||||
// Cubic implements the cubic algorithm from TCP
|
||||
type Cubic struct {
|
||||
clock Clock
|
||||
|
||||
// Number of connections to simulate.
|
||||
numConnections int
|
||||
|
||||
@@ -67,9 +65,8 @@ type Cubic struct {
|
||||
}
|
||||
|
||||
// NewCubic returns a new Cubic instance
|
||||
func NewCubic(clock Clock) *Cubic {
|
||||
func NewCubic() *Cubic {
|
||||
c := &Cubic{
|
||||
clock: clock,
|
||||
numConnections: defaultNumConnections,
|
||||
}
|
||||
c.Reset()
|
||||
|
||||
@@ -23,7 +23,6 @@ type cubicSender struct {
|
||||
rttStats congestion.RTTStatsProvider
|
||||
cubic *Cubic
|
||||
pacer *pacer
|
||||
clock Clock
|
||||
|
||||
reno bool
|
||||
|
||||
@@ -61,12 +60,10 @@ var (
|
||||
|
||||
// NewCubicSender makes a new cubic sender
|
||||
func NewCubicSender(
|
||||
clock Clock,
|
||||
initialMaxDatagramSize congestion.ByteCount,
|
||||
reno bool,
|
||||
) *cubicSender {
|
||||
return newCubicSender(
|
||||
clock,
|
||||
reno,
|
||||
initialMaxDatagramSize,
|
||||
initialCongestionWindow*initialMaxDatagramSize,
|
||||
@@ -75,7 +72,6 @@ func NewCubicSender(
|
||||
}
|
||||
|
||||
func newCubicSender(
|
||||
clock Clock,
|
||||
reno bool,
|
||||
initialMaxDatagramSize,
|
||||
initialCongestionWindow,
|
||||
@@ -89,8 +85,6 @@ func newCubicSender(
|
||||
initialMaxCongestionWindow: initialMaxCongestionWindow,
|
||||
congestionWindow: initialCongestionWindow,
|
||||
slowStartThreshold: MaxByteCount,
|
||||
cubic: NewCubic(clock),
|
||||
clock: clock,
|
||||
reno: reno,
|
||||
maxDatagramSize: initialMaxDatagramSize,
|
||||
}
|
||||
|
||||
@@ -96,7 +96,6 @@ const (
|
||||
|
||||
type bbrSender struct {
|
||||
rttStats congestion.RTTStatsProvider
|
||||
clock Clock
|
||||
pacer *Pacer
|
||||
|
||||
mode bbrMode
|
||||
@@ -244,12 +243,10 @@ type bbrSender struct {
|
||||
var _ congestion.CongestionControl = &bbrSender{}
|
||||
|
||||
func NewBbrSender(
|
||||
clock Clock,
|
||||
initialMaxDatagramSize congestion.ByteCount,
|
||||
initialCongestionWindowPackets congestion.ByteCount,
|
||||
) *bbrSender {
|
||||
return newBbrSender(
|
||||
clock,
|
||||
initialMaxDatagramSize,
|
||||
initialCongestionWindowPackets*initialMaxDatagramSize,
|
||||
congestion.MaxCongestionWindowPackets*initialMaxDatagramSize,
|
||||
@@ -257,13 +254,11 @@ func NewBbrSender(
|
||||
}
|
||||
|
||||
func newBbrSender(
|
||||
clock Clock,
|
||||
initialMaxDatagramSize,
|
||||
initialCongestionWindow,
|
||||
initialMaxCongestionWindow congestion.ByteCount,
|
||||
) *bbrSender {
|
||||
b := &bbrSender{
|
||||
clock: clock,
|
||||
mode: bbrModeStartup,
|
||||
sampler: newBandwidthSampler(roundTripCount(bandwidthWindowSize)),
|
||||
lastSentPacket: invalidPacketNumber,
|
||||
@@ -297,7 +292,7 @@ func newBbrSender(
|
||||
}
|
||||
*/
|
||||
|
||||
b.enterStartupMode(b.clock.Now())
|
||||
b.enterStartupMode()
|
||||
b.setHighCwndGain(derivedHighCWNDGain)
|
||||
|
||||
return b
|
||||
@@ -605,7 +600,7 @@ func (b *bbrSender) maybeUpdateMinRtt(now monotime.Time, sampleMinRtt time.Durat
|
||||
}
|
||||
|
||||
// Enters the STARTUP mode.
|
||||
func (b *bbrSender) enterStartupMode(now monotime.Time) {
|
||||
func (b *bbrSender) enterStartupMode() {
|
||||
b.mode = bbrModeStartup
|
||||
// b.maybeTraceStateChange(logging.CongestionStateStartup)
|
||||
b.pacingGain = b.highGain
|
||||
@@ -757,7 +752,7 @@ func (b *bbrSender) maybeEnterOrExitProbeRtt(now monotime.Time, isRoundStart, mi
|
||||
if now.Sub(b.exitProbeRttAt) >= 0 && b.probeRttRoundPassed {
|
||||
b.minRttTimestamp = now
|
||||
if !b.isAtFullBandwidth {
|
||||
b.enterStartupMode(now)
|
||||
b.enterStartupMode()
|
||||
} else {
|
||||
b.enterProbeBandwidthMode(now)
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package congestion
|
||||
|
||||
import (
|
||||
"github.com/metacubex/quic-go/monotime"
|
||||
)
|
||||
|
||||
// A Clock returns the current time
|
||||
type Clock interface {
|
||||
Now() monotime.Time
|
||||
}
|
||||
|
||||
// DefaultClock implements the Clock interface using the Go stdlib clock.
|
||||
type DefaultClock struct{}
|
||||
|
||||
var _ Clock = DefaultClock{}
|
||||
|
||||
// Now gets the current time
|
||||
func (DefaultClock) Now() monotime.Time {
|
||||
return monotime.Now()
|
||||
}
|
||||
@@ -30,7 +30,7 @@ require (
|
||||
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||
github.com/apernet/quic-go v0.54.1-0.20250907230547-eb32f8aec5e2 // indirect
|
||||
github.com/apernet/quic-go v0.54.1-0.20251024023933-5e0818a71079 // indirect
|
||||
github.com/cloudflare/circl v1.3.9 // indirect
|
||||
github.com/database64128/netx-go v0.0.0-20240905055117-62795b8b054a // indirect
|
||||
github.com/database64128/tfo-go/v2 v2.2.2 // indirect
|
||||
|
||||
@@ -42,10 +42,8 @@ github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1
|
||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||
github.com/apernet/go-tproxy v0.0.0-20230809025308-8f4723fd742f h1:uVh0qpEslrWjgzx9vOcyCqsOY3c9kofDZ1n+qaw35ZY=
|
||||
github.com/apernet/go-tproxy v0.0.0-20230809025308-8f4723fd742f/go.mod h1:xkkq9D4ygcldQQhKS/w9CadiCKwCngU7K9E3DaKahpM=
|
||||
github.com/apernet/quic-go v0.54.1-0.20250907230547-eb32f8aec5e2 h1:03y2WeGln3/QmBzm+KGQ3yej7Uz+76CqHoisdzYzf30=
|
||||
github.com/apernet/quic-go v0.54.1-0.20250907230547-eb32f8aec5e2/go.mod h1:Y4cCWi64O51TRUKDPy0ShA2/pevlWiWJJnlNo2fO2ds=
|
||||
github.com/apernet/sing-tun v0.2.6-0.20250726070404-c99085f9af13 h1:gzets97c/u5iMj1zjanMBVkIYOdaVw+RXPzTT1xQoyM=
|
||||
github.com/apernet/sing-tun v0.2.6-0.20250726070404-c99085f9af13/go.mod h1:S5IydyLSN/QAfvY+r2GoomPJ6hidtXWm/Ad18sJVssk=
|
||||
github.com/apernet/quic-go v0.54.1-0.20251024023933-5e0818a71079 h1:WgFl2esvC7FnVhhBvA+BJUgxyheiTAhJ4CIbRlaK22I=
|
||||
github.com/apernet/quic-go v0.54.1-0.20251024023933-5e0818a71079/go.mod h1:Y4cCWi64O51TRUKDPy0ShA2/pevlWiWJJnlNo2fO2ds=
|
||||
github.com/apernet/sing-tun v0.2.6-0.20250920121535-299f04629986 h1:w62V0oOO2Do0vXeZkx7mgZ2YFuUaRcO6rNZewI3xzuE=
|
||||
github.com/apernet/sing-tun v0.2.6-0.20250920121535-299f04629986/go.mod h1:S5IydyLSN/QAfvY+r2GoomPJ6hidtXWm/Ad18sJVssk=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
|
||||
@@ -5,7 +5,7 @@ go 1.23
|
||||
toolchain go1.25.1
|
||||
|
||||
require (
|
||||
github.com/apernet/quic-go v0.54.1-0.20250907230547-eb32f8aec5e2
|
||||
github.com/apernet/quic-go v0.54.1-0.20251024023933-5e0818a71079
|
||||
github.com/stretchr/testify v1.9.0
|
||||
go.uber.org/goleak v1.2.1
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
github.com/apernet/quic-go v0.54.1-0.20250907230547-eb32f8aec5e2 h1:03y2WeGln3/QmBzm+KGQ3yej7Uz+76CqHoisdzYzf30=
|
||||
github.com/apernet/quic-go v0.54.1-0.20250907230547-eb32f8aec5e2/go.mod h1:Y4cCWi64O51TRUKDPy0ShA2/pevlWiWJJnlNo2fO2ds=
|
||||
github.com/apernet/quic-go v0.54.1-0.20251024023933-5e0818a71079 h1:WgFl2esvC7FnVhhBvA+BJUgxyheiTAhJ4CIbRlaK22I=
|
||||
github.com/apernet/quic-go v0.54.1-0.20251024023933-5e0818a71079/go.mod h1:Y4cCWi64O51TRUKDPy0ShA2/pevlWiWJJnlNo2fO2ds=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
||||
@@ -6,7 +6,7 @@ toolchain go1.25.1
|
||||
|
||||
require (
|
||||
github.com/apernet/hysteria/core/v2 v2.0.0-00010101000000-000000000000
|
||||
github.com/apernet/quic-go v0.54.1-0.20250907230547-eb32f8aec5e2
|
||||
github.com/apernet/quic-go v0.54.1-0.20251024023933-5e0818a71079
|
||||
github.com/database64128/tfo-go/v2 v2.2.2
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.5
|
||||
github.com/miekg/dns v1.1.59
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||
github.com/apernet/quic-go v0.54.1-0.20250907230547-eb32f8aec5e2 h1:03y2WeGln3/QmBzm+KGQ3yej7Uz+76CqHoisdzYzf30=
|
||||
github.com/apernet/quic-go v0.54.1-0.20250907230547-eb32f8aec5e2/go.mod h1:Y4cCWi64O51TRUKDPy0ShA2/pevlWiWJJnlNo2fO2ds=
|
||||
github.com/apernet/quic-go v0.54.1-0.20251024023933-5e0818a71079 h1:WgFl2esvC7FnVhhBvA+BJUgxyheiTAhJ4CIbRlaK22I=
|
||||
github.com/apernet/quic-go v0.54.1-0.20251024023933-5e0818a71079/go.mod h1:Y4cCWi64O51TRUKDPy0ShA2/pevlWiWJJnlNo2fO2ds=
|
||||
github.com/cloudflare/circl v1.3.9 h1:QFrlgFYf2Qpi8bSpVPK1HBvWpx16v/1TZivyo7pGuBE=
|
||||
github.com/cloudflare/circl v1.3.9/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
|
||||
@@ -33,6 +33,7 @@ github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/apernet/quic-go v0.54.1-0.20251024023933-5e0818a71079/go.mod h1:Y4cCWi64O51TRUKDPy0ShA2/pevlWiWJJnlNo2fO2ds=
|
||||
github.com/armon/go-metrics v0.4.0 h1:yCQqn7dwca4ITXb+CbubHmedzaQYHhNhrEXLYUeEe8Q=
|
||||
github.com/armon/go-metrics v0.4.0/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
|
||||
|
||||
@@ -69,6 +69,7 @@ menu "Global build settings"
|
||||
default y
|
||||
|
||||
config USE_APK
|
||||
imply PACKAGE_apk-mbedtls
|
||||
bool "Use APK instead of OPKG to build distribution (EXPERIMENTAL)"
|
||||
|
||||
comment "General build options"
|
||||
|
||||
@@ -17,7 +17,7 @@ endif
|
||||
opkg_package_files = $(wildcard \
|
||||
$(foreach dir,$(PACKAGE_SUBDIRS), \
|
||||
$(foreach pkg,$(1), $(dir)/$(pkg)_*.ipk)))
|
||||
|
||||
|
||||
apk_package_files = $(wildcard \
|
||||
$(foreach dir,$(PACKAGE_SUBDIRS), \
|
||||
$(foreach pkg,$(1), $(dir)/$(pkg)_*.apk)))
|
||||
|
||||
@@ -46,7 +46,7 @@ define Package/base-files
|
||||
+SELINUX:busybox-selinux +!SELINUX:busybox
|
||||
TITLE:=Base filesystem for LEDE
|
||||
URL:=http://openwrt.org/
|
||||
VERSION:=$(PKG_RELEASE)~$(lastword $(subst -, ,$(REVISION)))
|
||||
VERSION:=$(PKG_RELEASE)-$(REVISION)
|
||||
endef
|
||||
|
||||
define Package/base-files/conffiles
|
||||
@@ -81,7 +81,7 @@ endef
|
||||
define ImageConfigOptions
|
||||
mkdir -p $(1)/lib/preinit
|
||||
echo 'pi_suppress_stderr="$(CONFIG_TARGET_PREINIT_SUPPRESS_STDERR)"' >$(1)/lib/preinit/00_preinit.conf
|
||||
echo 'fs_failsafe_wait_timeout=$(if $(CONFIG_TARGET_PREINIT_TIMEOUT),$(CONFIG_TARGET_PREINIT_TIMEOUT),4)' >>$(1)/lib/preinit/00_preinit.conf
|
||||
echo 'fs_failsafe_wait_timeout=$(if $(CONFIG_TARGET_PREINIT_TIMEOUT),$(CONFIG_TARGET_PREINIT_TIMEOUT),2)' >>$(1)/lib/preinit/00_preinit.conf
|
||||
echo 'pi_init_path="$(TARGET_INIT_PATH)"' >>$(1)/lib/preinit/00_preinit.conf
|
||||
echo 'pi_init_env=$(if $(CONFIG_TARGET_INIT_ENV),$(CONFIG_TARGET_INIT_ENV),"")' >>$(1)/lib/preinit/00_preinit.conf
|
||||
echo 'pi_init_cmd=$(if $(CONFIG_TARGET_INIT_CMD),$(CONFIG_TARGET_INIT_CMD),"/sbin/init")' >>$(1)/lib/preinit/00_preinit.conf
|
||||
@@ -248,7 +248,7 @@ endif
|
||||
|
||||
$(if $(CONFIG_TARGET_PREINIT_DISABLE_FAILSAFE), \
|
||||
rm -f $(1)/etc/banner.failsafe,)
|
||||
|
||||
|
||||
if [ ! -f $(TOPDIR)/feeds/luci/package.json ]; then \
|
||||
$(CP) ./luci/* $(1)/; \
|
||||
fi
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
CFG=/etc/board.json
|
||||
|
||||
. /usr/share/libubox/jshn.sh
|
||||
. /lib/functions/ipv4.sh
|
||||
|
||||
[ -s $CFG ] || /bin/board_detect || exit 1
|
||||
[ -s /etc/config/network -a -s /etc/config/system ] && exit 0
|
||||
@@ -43,16 +42,16 @@ generate_static_network() {
|
||||
set network.loopback='interface'
|
||||
set network.loopback.device='lo'
|
||||
set network.loopback.proto='static'
|
||||
add_list network.loopback.ipaddr='127.0.0.1/8'
|
||||
delete network.globals
|
||||
set network.globals='globals'
|
||||
set network.globals.dhcp_default_duid='auto'
|
||||
set network.loopback.ipaddr='127.0.0.1'
|
||||
set network.loopback.netmask='255.0.0.0'
|
||||
EOF
|
||||
[ -e /proc/sys/net/ipv6 ] && {
|
||||
uci -q batch <<-EOF
|
||||
set network.globals.ula_prefix='auto'
|
||||
EOF
|
||||
}
|
||||
[ -e /proc/sys/net/ipv6 ] && {
|
||||
uci -q batch <<-EOF
|
||||
delete network.globals
|
||||
set network.globals='globals'
|
||||
set network.globals.ula_prefix='auto'
|
||||
EOF
|
||||
}
|
||||
|
||||
if json_is_a dsl object; then
|
||||
json_select dsl
|
||||
@@ -161,19 +160,18 @@ generate_network() {
|
||||
|
||||
case "$protocol" in
|
||||
static)
|
||||
local ipad netm prefix
|
||||
local ipad
|
||||
case "$1" in
|
||||
lan) ipad=${ipaddr:-"192.168.1.1"} ;;
|
||||
*) ipad=${ipaddr:-"192.168.$((addr_offset++)).1"} ;;
|
||||
esac
|
||||
|
||||
netm=${netmask:-"255.255.255.0"}
|
||||
str2ip netm "$netm"
|
||||
netmask2prefix prefix "$netm"
|
||||
|
||||
uci -q batch <<-EOF
|
||||
set network.$1.proto='static'
|
||||
add_list network.$1.ipaddr='$ipad/$prefix'
|
||||
set network.$1.ipaddr='$ipad'
|
||||
set network.$1.netmask='$netm'
|
||||
EOF
|
||||
[ -e /proc/sys/net/ipv6 ] && uci set network.$1.ip6assign='60'
|
||||
;;
|
||||
@@ -323,11 +321,11 @@ generate_static_system() {
|
||||
delete system.ntp
|
||||
set system.ntp='timeserver'
|
||||
set system.ntp.enabled='1'
|
||||
set system.ntp.enable_server='0'
|
||||
add_list system.ntp.server='0.openwrt.pool.ntp.org'
|
||||
add_list system.ntp.server='1.openwrt.pool.ntp.org'
|
||||
add_list system.ntp.server='2.openwrt.pool.ntp.org'
|
||||
add_list system.ntp.server='3.openwrt.pool.ntp.org'
|
||||
set system.ntp.enable_server='1'
|
||||
add_list system.ntp.server='time.apple.com'
|
||||
add_list system.ntp.server='time.google.com'
|
||||
add_list system.ntp.server='time.windows.com'
|
||||
add_list system.ntp.server='time.cloudflare.com'
|
||||
EOF
|
||||
|
||||
if json_is_a system object; then
|
||||
|
||||
@@ -10,6 +10,7 @@ uci_apply_defaults() {
|
||||
cd /etc/uci-defaults || return 0
|
||||
files="$(ls)"
|
||||
[ -z "$files" ] && return 0
|
||||
mkdir -p /tmp/.uci
|
||||
applied=""
|
||||
for file in $files; do
|
||||
( . "./$(basename $file)" ) && applied="$applied $file"
|
||||
@@ -43,7 +44,6 @@ boot() {
|
||||
grep -q pstore /proc/filesystems && /bin/mount -o nosuid,nodev,noexec,noatime -t pstore pstore /sys/fs/pstore
|
||||
[ "$FAILSAFE" = "true" ] && touch /tmp/.failsafe
|
||||
|
||||
touch /tmp/.config_pending
|
||||
/sbin/kmodloader
|
||||
|
||||
[ ! -f /etc/config/wireless ] && {
|
||||
@@ -51,14 +51,10 @@ boot() {
|
||||
sleep 1
|
||||
}
|
||||
|
||||
mkdir -p /tmp/.uci
|
||||
[ -f /etc/uci-defaults/30_uboot-envtools ] && (. /etc/uci-defaults/30_uboot-envtools)
|
||||
/bin/config_generate
|
||||
rm -f /tmp/.config_pending
|
||||
/sbin/wifi config
|
||||
uci_apply_defaults
|
||||
sync
|
||||
|
||||
|
||||
# temporary hack until configd exists
|
||||
/sbin/reload_config
|
||||
}
|
||||
|
||||
@@ -38,24 +38,3 @@ in order to prevent unauthorized SSH logins.
|
||||
--------------------------------------------------
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ -x /usr/bin/apk ]; then
|
||||
cat << EOF
|
||||
|
||||
OpenWrt recently switched to the "apk" package manager!
|
||||
|
||||
OPKG Command APK Equivalent Description
|
||||
------------------------------------------------------------------
|
||||
opkg install <pkg> apk add <pkg> Install a package
|
||||
opkg remove <pkg> apk del <pkg> Remove a package
|
||||
opkg upgrade apk upgrade Upgrade all packages
|
||||
opkg files <pkg> apk info -L <pkg> List package contents
|
||||
opkg list-installed apk info List installed packages
|
||||
opkg update apk update Update package lists
|
||||
opkg search <pkg> apk search <pkg> Search for packages
|
||||
------------------------------------------------------------------
|
||||
|
||||
For more https://openwrt.org/docs/guide-user/additional-software/opkg-to-apk-cheatsheet
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
# User defined entries should be added to this file not to /etc/sysctl.d/* as
|
||||
# that directory is not backed-up by default and will not survive a reimage
|
||||
# Defaults are configured in /etc/sysctl.d/* and can be customized in this file
|
||||
|
||||
net.bridge.bridge-nf-call-arptables = 0
|
||||
net.bridge.bridge-nf-call-ip6tables = 0
|
||||
net.bridge.bridge-nf-call-iptables = 0
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
. /lib/functions.sh
|
||||
|
||||
migrate_ports() {
|
||||
local config="$1"
|
||||
local type ports ifname
|
||||
|
||||
config_get type "$config" type
|
||||
[ "$type" != "bridge" ] && return
|
||||
|
||||
config_get ports "$config" ports
|
||||
[ -n "$ports" ] && return
|
||||
|
||||
config_get ifname "$config" ifname
|
||||
[ -z "$ifname" ] && return
|
||||
|
||||
for port in $ifname; do
|
||||
uci add_list network.$config.ports="$port"
|
||||
done
|
||||
uci delete network.$config.ifname
|
||||
}
|
||||
|
||||
migrate_bridge() {
|
||||
local config="$1"
|
||||
local type ifname
|
||||
|
||||
config_get type "$config" type
|
||||
[ "$type" != "bridge" ] && return
|
||||
|
||||
config_get ifname "$config" ifname
|
||||
|
||||
uci -q batch <<-EOF
|
||||
add network device
|
||||
set network.@device[-1].name='br-$config'
|
||||
set network.@device[-1].type='bridge'
|
||||
EOF
|
||||
for port in $ifname; do
|
||||
uci add_list network.@device[-1].ports="$port"
|
||||
done
|
||||
|
||||
uci -q batch <<-EOF
|
||||
delete network.$config.type
|
||||
delete network.$config.ifname
|
||||
set network.$config.device='br-$config'
|
||||
EOF
|
||||
}
|
||||
|
||||
config_load network
|
||||
config_foreach migrate_ports device
|
||||
config_foreach migrate_bridge interface
|
||||
@@ -1,9 +0,0 @@
|
||||
[ "$(uci -q get network.globals.dhcp_default_duid)" != "auto" ] && exit 0
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
# DUID-UUID - RFC6355
|
||||
set network.globals.dhcp_default_duid="$(hexdump -vn 16 -e '"0004" 2/2 "%x"' /dev/urandom)"
|
||||
commit network
|
||||
EOF
|
||||
|
||||
exit 0
|
||||
@@ -211,14 +211,9 @@ config_list_foreach() {
|
||||
|
||||
default_prerm() {
|
||||
local root="${IPKG_INSTROOT}"
|
||||
[ -z "$pkgname" ] && local pkgname="$(basename ${1%.*})"
|
||||
local pkgname="$(basename ${1%.*})"
|
||||
local ret=0
|
||||
local filelist="${root}/usr/lib/opkg/info/${pkgname}.list"
|
||||
[ -f "$root/lib/apk/packages/${pkgname}.list" ] && filelist="$root/lib/apk/packages/${pkgname}.list"
|
||||
|
||||
if [ -e "$root/lib/apk/packages/${pkgname}.alternatives" ]; then
|
||||
update_alternatives remove "${pkgname}"
|
||||
fi
|
||||
|
||||
if [ -f "$root/usr/lib/opkg/info/${pkgname}.prerm-pkg" ]; then
|
||||
( . "$root/usr/lib/opkg/info/${pkgname}.prerm-pkg" )
|
||||
@@ -241,11 +236,8 @@ default_prerm() {
|
||||
}
|
||||
|
||||
add_group_and_user() {
|
||||
[ -z "$pkgname" ] && local pkgname="$(basename ${1%.*})"
|
||||
local pkgname="$(basename ${1%.*})"
|
||||
local rusers="$(sed -ne 's/^Require-User: *//p' $root/usr/lib/opkg/info/${pkgname}.control 2>/dev/null)"
|
||||
if [ -f "$root/lib/apk/packages/${pkgname}.rusers" ]; then
|
||||
local rusers="$(cat $root/lib/apk/packages/${pkgname}.rusers)"
|
||||
fi
|
||||
|
||||
if [ -n "$rusers" ]; then
|
||||
local tuple oIFS="$IFS"
|
||||
@@ -295,70 +287,13 @@ add_group_and_user() {
|
||||
fi
|
||||
}
|
||||
|
||||
update_alternatives() {
|
||||
local root="${IPKG_INSTROOT}"
|
||||
local action="$1"
|
||||
local pkgname="$2"
|
||||
|
||||
if [ -f "$root/lib/apk/packages/${pkgname}.alternatives" ]; then
|
||||
for pkg_alt in $(cat $root/lib/apk/packages/${pkgname}.alternatives); do
|
||||
local best_prio=0;
|
||||
local best_src="/bin/busybox";
|
||||
pkg_prio=${pkg_alt%%:*};
|
||||
pkg_target=${pkg_alt#*:};
|
||||
pkg_target=${pkg_target%:*};
|
||||
pkg_src=${pkg_alt##*:};
|
||||
|
||||
if [ -e "$root/$target" ]; then
|
||||
for alts in $root/lib/apk/packages/*.alternatives; do
|
||||
for alt in $(cat $alts); do
|
||||
prio=${alt%%:*};
|
||||
target=${alt#*:};
|
||||
target=${target%:*};
|
||||
src=${alt##*:};
|
||||
|
||||
if [ "$target" = "$pkg_target" ] &&
|
||||
[ "$src" != "$pkg_src" ] &&
|
||||
[ "$best_prio" -lt "$prio" ]; then
|
||||
best_prio=$prio;
|
||||
best_src=$src;
|
||||
fi
|
||||
done
|
||||
done
|
||||
fi
|
||||
case "$action" in
|
||||
install)
|
||||
if [ "$best_prio" -lt "$pkg_prio" ]; then
|
||||
ln -sf "$pkg_src" "$root/$pkg_target"
|
||||
echo "add alternative: $pkg_target -> $pkg_src"
|
||||
fi
|
||||
;;
|
||||
remove)
|
||||
if [ "$best_prio" -lt "$pkg_prio" ]; then
|
||||
ln -sf "$best_src" "$root/$pkg_target"
|
||||
echo "add alternative: $pkg_target -> $best_src"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
default_postinst() {
|
||||
local root="${IPKG_INSTROOT}"
|
||||
[ -z "$pkgname" ] && local pkgname="$(basename ${1%.*})"
|
||||
local filelist="${root}/usr/lib/opkg/info/${pkgname}.list"
|
||||
[ -f "$root/lib/apk/packages/${pkgname}.list" ] && filelist="$root/lib/apk/packages/${pkgname}.list"
|
||||
local pkgname="$(basename ${1%.*})"
|
||||
local filelist="/usr/lib/opkg/info/${pkgname}.list"
|
||||
local ret=0
|
||||
|
||||
if [ -e "${root}/usr/lib/opkg/info/${pkgname}.list" ]; then
|
||||
filelist="${root}/usr/lib/opkg/info/${pkgname}.list"
|
||||
add_group_and_user "${pkgname}"
|
||||
fi
|
||||
|
||||
if [ -e "${root}/lib/apk/packages/${pkgname}.alternatives" ]; then
|
||||
update_alternatives install "${pkgname}"
|
||||
fi
|
||||
add_group_and_user "${pkgname}"
|
||||
|
||||
if [ -d "$root/rootfs-overlay" ]; then
|
||||
cp -R $root/rootfs-overlay/. $root/
|
||||
|
||||
@@ -201,7 +201,7 @@ ath11k_remove_regdomain() {
|
||||
|
||||
regdomain=$(hexdump -v -n 2 -s 0x34 -e '1/1 "%02x"' $target)
|
||||
caldata_patch_data "0000" 0x34 0xa "$target"
|
||||
|
||||
|
||||
for offset in 0x450 0x458 0x500 0x5a8; do
|
||||
regdomain_data=$(hexdump -v -n 2 -s $offset -e '1/1 "%02x"' $target)
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ get_mac_ascii() {
|
||||
local key="$2"
|
||||
local mac_dirty
|
||||
|
||||
mac_dirty=$(strings "$part" | tr -d ' \t' | sed -n 's/^'"$key"'=//p' | head -n 1)
|
||||
mac_dirty=$(strings "$part" | sed -n "s/^$key\\(=\\?\)//p")
|
||||
|
||||
# "canonicalize" mac
|
||||
[ -n "$mac_dirty" ] && macaddr_canonicalize "$mac_dirty"
|
||||
@@ -275,7 +275,7 @@ macaddr_unsetbit_mc() {
|
||||
|
||||
macaddr_random() {
|
||||
local randsrc=$(get_mac_binary /dev/urandom 0)
|
||||
|
||||
|
||||
echo "$(macaddr_unsetbit_mc "$(macaddr_setbit_la "${randsrc}")")"
|
||||
}
|
||||
|
||||
|
||||
@@ -9,14 +9,9 @@ indicate_failsafe_led () {
|
||||
|
||||
indicate_failsafe() {
|
||||
[ "$pi_preinit_no_failsafe" = "y" ] && return
|
||||
local consoles="$(cat /sys/class/tty/console/active)"
|
||||
[ -n "$consoles" ] || consoles=console
|
||||
for console in $consoles; do
|
||||
[ -c "/dev/$console" ] && echo "- failsafe -" >"/dev/$console"
|
||||
done
|
||||
echo "- failsafe -"
|
||||
preinit_net_echo "Entering Failsafe!\n"
|
||||
indicate_failsafe_led
|
||||
echo OpenWrt-failsafe > /proc/sys/kernel/hostname
|
||||
}
|
||||
|
||||
boot_hook_add failsafe indicate_failsafe
|
||||
|
||||
@@ -36,6 +36,7 @@ compose_rootfs_mount_options() {
|
||||
do_mount_root() {
|
||||
mount_root start "$(compose_rootfs_mount_options)"
|
||||
boot_run_hook preinit_mount_root
|
||||
[ ! -f /etc/bench.log ] && touch /etc/bench.log
|
||||
[ -f /sysupgrade.tgz -o -f /tmp/sysupgrade.tar ] && {
|
||||
echo "- config restore -"
|
||||
cp /etc/passwd /etc/group /etc/shadow /tmp
|
||||
|
||||
@@ -5,19 +5,11 @@ failsafe_shell() {
|
||||
local consoles="$(cat /sys/class/tty/console/active)"
|
||||
[ -n "$consoles" ] || consoles=console
|
||||
for console in $consoles; do
|
||||
case "$console" in
|
||||
console|tty[0-9]*)
|
||||
term=${TERM:-linux}
|
||||
;;
|
||||
*)
|
||||
term=vt102
|
||||
;;
|
||||
esac
|
||||
# Running asynchronously via the shell's & would ignore SIGINT,
|
||||
# breaking ^C. Use start-stop-daemon instead.
|
||||
[ -c "/dev/$console" ] && start-stop-daemon -Sb -p /dev/null -- env -i ash -c "while true; do setsid -c env -i USER=root LOGNAME=root SHELL=/bin/ash TERM="$term" ash --login <\"/dev/$console\" >\"/dev/$console\" 2>\"/dev/$console\"; sleep 1; done"
|
||||
[ -c "/dev/$console" ] && while true; do
|
||||
ash --login <"/dev/$console" >"/dev/$console" 2>"/dev/$console"
|
||||
sleep 1
|
||||
done &
|
||||
done
|
||||
|
||||
}
|
||||
|
||||
boot_hook_add failsafe failsafe_shell
|
||||
|
||||
@@ -165,6 +165,23 @@ part_magic_fat() {
|
||||
[ "$magic" = "FAT" ] || [ "$magic_fat32" = "FAT32" ]
|
||||
}
|
||||
|
||||
fitblk_get_bootdev() {
|
||||
[ -e /sys/firmware/devicetree/base/chosen/rootdisk ] || return
|
||||
|
||||
local rootdisk="$(cat /sys/firmware/devicetree/base/chosen/rootdisk)"
|
||||
local handle bootdev
|
||||
for handle in /sys/class/block/*/of_node/phandle /sys/class/block/*/device/of_node/phandle; do
|
||||
[ ! -e "$handle" ] && continue
|
||||
if [ "$rootdisk" = "$(cat $handle)" ]; then
|
||||
bootdev="${handle%/of_node/phandle}"
|
||||
bootdev="${bootdev%/device}"
|
||||
bootdev="${bootdev#/sys/class/block/}"
|
||||
echo "$bootdev"
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
export_bootdevice() {
|
||||
local cmdline uuid blockdev uevent line class
|
||||
local MAJOR MINOR DEVNAME DEVTYPE
|
||||
@@ -196,6 +213,7 @@ export_bootdevice() {
|
||||
done
|
||||
;;
|
||||
/dev/*)
|
||||
[ "$rootpart" = "/dev/fit0" ] && rootpart="$(fitblk_get_bootdev)"
|
||||
uevent="/sys/class/block/${rootpart##*/}/../uevent"
|
||||
;;
|
||||
0x[a-f0-9][a-f0-9][a-f0-9] | 0x[a-f0-9][a-f0-9][a-f0-9][a-f0-9] | \
|
||||
|
||||
@@ -8,38 +8,22 @@ emmc_upgrade_tar() {
|
||||
[ "$CI_KERNPART" -a -z "$EMMC_KERN_DEV" ] && export EMMC_KERN_DEV="$(find_mmc_part $CI_KERNPART $CI_ROOTDEV)"
|
||||
[ "$CI_ROOTPART" -a -z "$EMMC_ROOT_DEV" ] && export EMMC_ROOT_DEV="$(find_mmc_part $CI_ROOTPART $CI_ROOTDEV)"
|
||||
[ "$CI_DATAPART" -a -z "$EMMC_DATA_DEV" ] && export EMMC_DATA_DEV="$(find_mmc_part $CI_DATAPART $CI_ROOTDEV)"
|
||||
[ "$CI_DTBPART" -a -z "$EMMC_DTB_DEV" ] && export EMMC_DTB_DEV="$(find_mmc_part $CI_DTBPART $CI_ROOTDEV)"
|
||||
local has_kernel
|
||||
local has_rootfs
|
||||
local has_dtb
|
||||
local gz
|
||||
local board_dir
|
||||
[ "$(identify_magic_long $(get_magic_long "$tar_file" cat))" = "gzip" ] && \
|
||||
gz="z"
|
||||
board_dir=$(tar t${gz}f "$tar_file" | grep -m 1 '^sysupgrade-.*/$')
|
||||
local board_dir=$(tar tf "$tar_file" | grep -m 1 '^sysupgrade-.*/$')
|
||||
board_dir=${board_dir%/}
|
||||
|
||||
tar t${gz}f "$tar_file" ${board_dir}/kernel 1>/dev/null 2>/dev/null && has_kernel=1
|
||||
tar t${gz}f "$tar_file" ${board_dir}/root 1>/dev/null 2>/dev/null && has_rootfs=1
|
||||
tar t${gz}f "$tar_file" ${board_dir}/dtb 1>/dev/null 2>/dev/null && has_dtb=1
|
||||
|
||||
[ "$has_rootfs" = 1 -a "$EMMC_ROOT_DEV" ] && {
|
||||
# Invalidate kernel image while rootfs is being written
|
||||
[ "$has_kernel" = 1 -a "$EMMC_KERN_DEV" ] && {
|
||||
dd if=/dev/zero of="$EMMC_KERN_DEV" bs=512 count=8
|
||||
sync
|
||||
}
|
||||
|
||||
export EMMC_ROOTFS_BLOCKS=$(($(tar x${gz}f "$tar_file" ${board_dir}/root -O | dd of="$EMMC_ROOT_DEV" bs=512 2>&1 | grep "records out" | cut -d' ' -f1)))
|
||||
# Account for 64KiB ROOTDEV_OVERLAY_ALIGN in libfstools
|
||||
EMMC_ROOTFS_BLOCKS=$(((EMMC_ROOTFS_BLOCKS + 127) & ~127))
|
||||
sync
|
||||
}
|
||||
[ "$has_dtb" = 1 -a "$EMMC_DTB_DEV" ] &&
|
||||
export EMMC_DTB_BLOCKS=$(($(tar x${gz}f "$tar_file" ${board_dir}/dtb -O | dd of="$EMMC_DTB_DEV" bs=512 2>&1 | grep "records out" | cut -d' ' -f1)))
|
||||
tar tf "$tar_file" ${board_dir}/kernel 1>/dev/null 2>/dev/null && has_kernel=1
|
||||
tar tf "$tar_file" ${board_dir}/root 1>/dev/null 2>/dev/null && has_rootfs=1
|
||||
|
||||
[ "$has_kernel" = 1 -a "$EMMC_KERN_DEV" ] &&
|
||||
export EMMC_KERNEL_BLOCKS=$(($(tar x${gz}f "$tar_file" ${board_dir}/kernel -O | dd of="$EMMC_KERN_DEV" bs=512 2>&1 | grep "records out" | cut -d' ' -f1)))
|
||||
export EMMC_KERNEL_BLOCKS=$(($(tar xf "$tar_file" ${board_dir}/kernel -O | dd of="$EMMC_KERN_DEV" bs=512 2>&1 | grep "records out" | cut -d' ' -f1)))
|
||||
|
||||
[ "$has_rootfs" = 1 -a "$EMMC_ROOT_DEV" ] && {
|
||||
export EMMC_ROOTFS_BLOCKS=$(($(tar xf "$tar_file" ${board_dir}/root -O | dd of="$EMMC_ROOT_DEV" bs=512 2>&1 | grep "records out" | cut -d' ' -f1)))
|
||||
# Account for 64KiB ROOTDEV_OVERLAY_ALIGN in libfstools
|
||||
EMMC_ROOTFS_BLOCKS=$(((EMMC_ROOTFS_BLOCKS + 127) & ~127))
|
||||
}
|
||||
|
||||
if [ -z "$UPGRADE_BACKUP" ]; then
|
||||
if [ "$EMMC_DATA_DEV" ]; then
|
||||
|
||||
@@ -42,9 +42,7 @@ fwtool_check_image() {
|
||||
v "Invalid image metadata"
|
||||
return 1
|
||||
}
|
||||
# Step 1. check if oem_name file exist and is not empty
|
||||
# If the above is true store the contents (b3000) in $oem value for later
|
||||
[ -s /tmp/sysinfo/oem_name ] && oem="$(cat /tmp/sysinfo/oem_name)"
|
||||
|
||||
device="$(cat /tmp/sysinfo/board_name)"
|
||||
devicecompat="$(uci -q get system.@system[0].compat_version)"
|
||||
[ -n "$devicecompat" ] || devicecompat="1.0"
|
||||
@@ -63,16 +61,7 @@ fwtool_check_image() {
|
||||
json_get_keys dev_keys
|
||||
for k in $dev_keys; do
|
||||
json_get_var dev "$k"
|
||||
# Step 2.
|
||||
# lets start with the original case [ "$dev" = "$device" ]
|
||||
# if the evaluated firmware is vanila openwrt, this evals as true -ie
|
||||
# [ ("$dev" == "glinet.gl-b3000") == ("$device" == "glinet,gl-b3000") ]
|
||||
# however if the firmware is oem then $dev = b3000 and the above check fails resulting
|
||||
# in the erroneous warnings.
|
||||
# so we add the secondary check [ "$dev" = "$oem" ];
|
||||
# If in Step 1 the oem_file was found and valid, the $oem == "b3000" so
|
||||
# [ ("$dev" == "b3000) == ("$oem" == "b3000") ] so firmware is valid oem
|
||||
if [ "$dev" = "$device" ] || [ "$dev" = "$oem" ]; then
|
||||
if [ "$dev" = "$device" ]; then
|
||||
# major compat version -> no sysupgrade
|
||||
if [ "${devicecompat%.*}" != "${imagecompat%.*}" ]; then
|
||||
v "The device is supported, but this image is incompatible for sysupgrade based on the image version ($devicecompat->$imagecompat)."
|
||||
@@ -81,16 +70,7 @@ fwtool_check_image() {
|
||||
fi
|
||||
|
||||
# minor compat version -> sysupgrade with -n required
|
||||
# Step 3.
|
||||
# here we must check if $dev == $oem to use this native compatability check
|
||||
# so we add the check for [ "$dev" = "$oem" ]
|
||||
if (([ "${devicecompat#.*}" != "${imagecompat#.*}" ] || [ "$dev" = "$oem" ])) && [ "$SAVE_CONFIG" = "1" ]; then
|
||||
# Step 4.
|
||||
# here we have to gaurd against the default case, oem may exsist and default will pass
|
||||
# the original check [ "${devicecompat#.*}" != "${imagecompat#.*}" ] so we must
|
||||
# explicitly check $dev == $oem, if it is we update(reuse) the $devicecompat and imagecompat
|
||||
# variable to reflect the case - ( Openwrt -> OEM )
|
||||
[ "$dev" = "$oem" ] && devicecompat="Openwrt " && imagecompat=" OEM"
|
||||
if [ "${devicecompat#.*}" != "${imagecompat#.*}" ] && [ "$SAVE_CONFIG" = "1" ]; then
|
||||
[ "$IGNORE_MINOR_COMPAT" = 1 ] && return 0
|
||||
v "The device is supported, but the config is incompatible to the new image ($devicecompat->$imagecompat). Please upgrade without keeping config (sysupgrade -n)."
|
||||
[ -n "$compatmessage" ] && v "$compatmessage"
|
||||
|
||||
@@ -57,11 +57,11 @@ nand_find_ubi() {
|
||||
}
|
||||
|
||||
nand_get_magic_long() {
|
||||
($2 < "$1" | dd bs=4 "skip=${3:-0}" count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2> /dev/null
|
||||
(${3}cat "$1" | dd bs=4 "skip=${2:-0}" count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2> /dev/null
|
||||
}
|
||||
|
||||
get_magic_long_tar() {
|
||||
($2 < "$1" | tar xOf - "$3" | dd bs=4 count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2> /dev/null
|
||||
(tar xO${3}f "$1" "$2" | dd bs=4 count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2> /dev/null
|
||||
}
|
||||
|
||||
identify() {
|
||||
@@ -73,7 +73,7 @@ identify_tar() {
|
||||
}
|
||||
|
||||
identify_if_gzip() {
|
||||
if [ "$(identify "$1" "cat")" = gzip ]; then echo -n z; fi
|
||||
if [ "$(identify "$1")" = gzip ]; then echo -n z; fi
|
||||
}
|
||||
|
||||
nand_restore_config() {
|
||||
@@ -111,7 +111,7 @@ nand_remove_ubiblock() {
|
||||
|
||||
local ubiblk="ubiblock${ubivol:3}"
|
||||
if [ -e "/dev/$ubiblk" ]; then
|
||||
umount "/dev/$ubiblk" 2>/dev/null && echo "unmounted /dev/$ubiblk" || :
|
||||
umount "/dev/$ubiblk" && echo "unmounted /dev/$ubiblk" || :
|
||||
if ! ubiblock -r "/dev/$ubivol"; then
|
||||
echo "cannot remove $ubiblk"
|
||||
return 1
|
||||
@@ -217,16 +217,6 @@ nand_upgrade_prepare_ubi() {
|
||||
[ "$root_ubivol" ] && ubirmvol /dev/$root_ubidev -N "$CI_ROOTPART" || :
|
||||
[ "$data_ubivol" ] && ubirmvol /dev/$root_ubidev -N rootfs_data || :
|
||||
|
||||
# create provisioning vol
|
||||
if [ "${UPGRADE_OPT_ADD_PROVISIONING:-0}" -gt 0 ]; then
|
||||
[ -n "$(nand_find_volume $root_ubidev provisioning)" ] || {
|
||||
if ! ubimkvol /dev/$root_ubidev -N provisioning -s 131072; then
|
||||
echo "cannot create provisioning volume"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
fi
|
||||
|
||||
# create kernel vol
|
||||
if [ -n "$kernel_length" ]; then
|
||||
if ! ubimkvol /dev/$kern_ubidev -N "$CI_KERNPART" -s $kernel_length; then
|
||||
@@ -269,64 +259,64 @@ nand_upgrade_prepare_ubi() {
|
||||
# Write the UBI image to MTD ubi partition
|
||||
nand_upgrade_ubinized() {
|
||||
local ubi_file="$1"
|
||||
local cmd="$2"
|
||||
local gz="$2"
|
||||
|
||||
local ubi_length=$( ($cmd < "$ubi_file" | wc -c) 2> /dev/null)
|
||||
local ubi_length=$( (${gz}cat "$ubi_file" | wc -c) 2> /dev/null)
|
||||
|
||||
nand_detach_ubi "$CI_UBIPART" || return 1
|
||||
|
||||
local mtdnum="$( find_mtd_index "$CI_UBIPART" )"
|
||||
$cmd < "$ubi_file" | ubiformat "/dev/mtd$mtdnum" -S "$ubi_length" -y -f - && ubiattach -m "$mtdnum"
|
||||
${gz}cat "$ubi_file" | ubiformat "/dev/mtd$mtdnum" -S "$ubi_length" -y -f - && ubiattach -m "$mtdnum"
|
||||
}
|
||||
|
||||
# Write the UBIFS image to UBI rootfs volume
|
||||
nand_upgrade_ubifs() {
|
||||
local ubifs_file="$1"
|
||||
local cmd="$2"
|
||||
local gz="$2"
|
||||
|
||||
local ubifs_length=$( ($cmd < "$ubifs_file" | wc -c) 2> /dev/null)
|
||||
local ubifs_length=$( (${gz}cat "$ubifs_file" | wc -c) 2> /dev/null)
|
||||
|
||||
nand_upgrade_prepare_ubi "$ubifs_length" "ubifs" "" "" || return 1
|
||||
|
||||
local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
|
||||
local root_ubivol="$(nand_find_volume $ubidev "$CI_ROOTPART")"
|
||||
$cmd < "$ubifs_file" | ubiupdatevol /dev/$root_ubivol -s "$ubifs_length" -
|
||||
${gz}cat "$ubifs_file" | ubiupdatevol /dev/$root_ubivol -s "$ubifs_length" -
|
||||
}
|
||||
|
||||
# Write the FIT image to UBI kernel volume
|
||||
nand_upgrade_fit() {
|
||||
local fit_file="$1"
|
||||
local cmd="$2"
|
||||
local gz="$2"
|
||||
|
||||
local fit_length=$( ($cmd < "$fit_file" | wc -c) 2> /dev/null)
|
||||
local fit_length=$( (${gz}cat "$fit_file" | wc -c) 2> /dev/null)
|
||||
|
||||
nand_upgrade_prepare_ubi "" "" "$fit_length" "1" || return 1
|
||||
|
||||
local fit_ubidev="$(nand_find_ubi "$CI_UBIPART")"
|
||||
local fit_ubivol="$(nand_find_volume $fit_ubidev "$CI_KERNPART")"
|
||||
$cmd < "$fit_file" | ubiupdatevol /dev/$fit_ubivol -s "$fit_length" -
|
||||
${gz}cat "$fit_file" | ubiupdatevol /dev/$fit_ubivol -s "$fit_length" -
|
||||
}
|
||||
|
||||
# Write images in the TAR file to MTD partitions and/or UBI volumes as required
|
||||
nand_upgrade_tar() {
|
||||
local tar_file="$1"
|
||||
local cmd="${2:-cat}"
|
||||
local gz="$2"
|
||||
local jffs2_markers="${CI_JFFS2_CLEAN_MARKERS:-0}"
|
||||
|
||||
# WARNING: This fails if tar contains more than one 'sysupgrade-*' directory.
|
||||
local board_dir="$($cmd < "$tar_file" | tar tf - | grep -m 1 '^sysupgrade-.*/$')"
|
||||
local board_dir="$(tar t${gz}f "$tar_file" | grep -m 1 '^sysupgrade-.*/$')"
|
||||
board_dir="${board_dir%/}"
|
||||
|
||||
local kernel_mtd kernel_length
|
||||
if [ "$CI_KERNPART" != "none" ]; then
|
||||
kernel_mtd="$(find_mtd_index "$CI_KERNPART")"
|
||||
kernel_length=$( ($cmd < "$tar_file" | tar xOf - "$board_dir/kernel" | wc -c) 2> /dev/null)
|
||||
kernel_length=$( (tar xO${gz}f "$tar_file" "$board_dir/kernel" | wc -c) 2> /dev/null)
|
||||
[ "$kernel_length" = 0 ] && kernel_length=
|
||||
fi
|
||||
local rootfs_length=$( ($cmd < "$tar_file" | tar xOf - "$board_dir/root" | wc -c) 2> /dev/null)
|
||||
local rootfs_length=$( (tar xO${gz}f "$tar_file" "$board_dir/root" | wc -c) 2> /dev/null)
|
||||
[ "$rootfs_length" = 0 ] && rootfs_length=
|
||||
local rootfs_type
|
||||
[ "$rootfs_length" ] && rootfs_type="$(identify_tar "$tar_file" "$cmd" "$board_dir/root")"
|
||||
[ "$rootfs_length" ] && rootfs_type="$(identify_tar "$tar_file" "$board_dir/root" "$gz")"
|
||||
|
||||
local ubi_kernel_length
|
||||
if [ "$kernel_length" ]; then
|
||||
@@ -347,23 +337,23 @@ nand_upgrade_tar() {
|
||||
if [ "$rootfs_length" ]; then
|
||||
local ubidev="$( nand_find_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" )"
|
||||
local root_ubivol="$( nand_find_volume $ubidev "$CI_ROOTPART" )"
|
||||
$cmd < "$tar_file" | tar xOf - "$board_dir/root" | \
|
||||
tar xO${gz}f "$tar_file" "$board_dir/root" | \
|
||||
ubiupdatevol /dev/$root_ubivol -s "$rootfs_length" -
|
||||
fi
|
||||
if [ "$kernel_length" ]; then
|
||||
if [ "$kernel_mtd" ]; then
|
||||
if [ "$jffs2_markers" = 1 ]; then
|
||||
flash_erase -j "/dev/mtd${kernel_mtd}" 0 0
|
||||
$cmd < "$tar_file" | tar xOf - "$board_dir/kernel" | \
|
||||
tar xO${gz}f "$tar_file" "$board_dir/kernel" | \
|
||||
nandwrite "/dev/mtd${kernel_mtd}" -
|
||||
else
|
||||
$cmd < "$tar_file" | tar xOf - "$board_dir/kernel" | \
|
||||
tar xO${gz}f "$tar_file" "$board_dir/kernel" | \
|
||||
mtd write - "$CI_KERNPART"
|
||||
fi
|
||||
else
|
||||
local ubidev="$( nand_find_ubi "${CI_KERN_UBIPART:-$CI_UBIPART}" )"
|
||||
local kern_ubivol="$( nand_find_volume $ubidev "$CI_KERNPART" )"
|
||||
$cmd < "$tar_file" | tar xOf - "$board_dir/kernel" | \
|
||||
tar xO${gz}f "$tar_file" "$board_dir/kernel" | \
|
||||
ubiupdatevol /dev/$kern_ubivol -s "$kernel_length" -
|
||||
fi
|
||||
fi
|
||||
@@ -373,9 +363,9 @@ nand_upgrade_tar() {
|
||||
|
||||
nand_verify_if_gzip_file() {
|
||||
local file="$1"
|
||||
local cmd="$2"
|
||||
local gz="$2"
|
||||
|
||||
if [ "$cmd" = zcat ]; then
|
||||
if [ "$gz" = z ]; then
|
||||
echo "verifying compressed sysupgrade file integrity"
|
||||
if ! gzip -t "$file"; then
|
||||
echo "corrupted compressed sysupgrade file"
|
||||
@@ -386,10 +376,10 @@ nand_verify_if_gzip_file() {
|
||||
|
||||
nand_verify_tar_file() {
|
||||
local file="$1"
|
||||
local cmd="$2"
|
||||
local gz="$2"
|
||||
|
||||
echo "verifying sysupgrade tar file integrity"
|
||||
if ! $cmd < "$file" | tar xOf - > /dev/null; then
|
||||
if ! tar xO${gz}f "$file" > /dev/null; then
|
||||
echo "corrupted sysupgrade tar file"
|
||||
return 1
|
||||
fi
|
||||
@@ -397,30 +387,28 @@ nand_verify_tar_file() {
|
||||
|
||||
nand_do_flash_file() {
|
||||
local file="$1"
|
||||
local cmd="$2"
|
||||
local file_type
|
||||
|
||||
[ -z "$cmd" ] && cmd="$(identify_if_gzip "$file")cat"
|
||||
file_type="$(identify "$file" "$cmd" "")"
|
||||
local gz="$(identify_if_gzip "$file")"
|
||||
local file_type="$(identify "$file" "" "$gz")"
|
||||
|
||||
[ ! "$(find_mtd_index "$CI_UBIPART")" ] && CI_UBIPART=rootfs
|
||||
|
||||
case "$file_type" in
|
||||
"fit")
|
||||
nand_verify_if_gzip_file "$file" "$cmd" || return 1
|
||||
nand_upgrade_fit "$file" "$cmd"
|
||||
nand_verify_if_gzip_file "$file" "$gz" || return 1
|
||||
nand_upgrade_fit "$file" "$gz"
|
||||
;;
|
||||
"ubi")
|
||||
nand_verify_if_gzip_file "$file" "$cmd" || return 1
|
||||
nand_upgrade_ubinized "$file" "$cmd"
|
||||
nand_verify_if_gzip_file "$file" "$gz" || return 1
|
||||
nand_upgrade_ubinized "$file" "$gz"
|
||||
;;
|
||||
"ubifs")
|
||||
nand_verify_if_gzip_file "$file" "$cmd" || return 1
|
||||
nand_upgrade_ubifs "$file" "$cmd"
|
||||
nand_verify_if_gzip_file "$file" "$gz" || return 1
|
||||
nand_upgrade_ubifs "$file" "$gz"
|
||||
;;
|
||||
*)
|
||||
nand_verify_tar_file "$file" "$cmd" || return 1
|
||||
nand_upgrade_tar "$file" "$cmd"
|
||||
nand_verify_tar_file "$file" "$gz" || return 1
|
||||
nand_upgrade_tar "$file" "$gz"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
@@ -431,26 +419,11 @@ nand_do_restore_config() {
|
||||
}
|
||||
|
||||
# Recognize type of passed file and start the upgrade process
|
||||
#
|
||||
# Supported firmware containers:
|
||||
# 1. Raw file
|
||||
# 2. Gzip
|
||||
# 3. Custom (requires passing extracting command)
|
||||
#
|
||||
# Supported data formats:
|
||||
# 1. Tar with kernel/rootfs
|
||||
# 2. UBI image (built using "ubinized")
|
||||
# 3. UBIFS image (to update UBI volume with)
|
||||
# 4. FIT image (to update UBI volume with)
|
||||
#
|
||||
# $(1): firmware file path
|
||||
# $(2): (optional) pipe command to extract firmware
|
||||
nand_do_upgrade() {
|
||||
local file="$1"
|
||||
local cmd="$2"
|
||||
|
||||
sync
|
||||
nand_do_flash_file "$file" "$cmd" && nand_do_upgrade_success
|
||||
nand_do_flash_file "$file" && nand_do_upgrade_success
|
||||
nand_do_upgrade_failed
|
||||
}
|
||||
|
||||
@@ -487,18 +460,18 @@ nand_do_platform_check() {
|
||||
local board_name="$1"
|
||||
local file="$2"
|
||||
|
||||
local cmd="$(identify_if_gzip "$file")cat"
|
||||
local file_type="$(identify "$file" "$cmd" "")"
|
||||
local control_length=$( ($cmd < "$file" | tar xOf - "sysupgrade-${board_name//,/_}/CONTROL" | wc -c) 2> /dev/null)
|
||||
local gz="$(identify_if_gzip "$file")"
|
||||
local file_type="$(identify "$file" "" "$gz")"
|
||||
local control_length=$( (tar xO${gz}f "$file" "sysupgrade-${board_name//,/_}/CONTROL" | wc -c) 2> /dev/null)
|
||||
|
||||
if [ "$control_length" = 0 ]; then
|
||||
control_length=$( ($cmd < "$file" | tar xOf - "sysupgrade-${board_name//_/,}/CONTROL" | wc -c) 2> /dev/null)
|
||||
control_length=$( (tar xO${gz}f "$file" "sysupgrade-${board_name//_/,}/CONTROL" | wc -c) 2> /dev/null)
|
||||
fi
|
||||
|
||||
if [ "$control_length" != 0 ]; then
|
||||
nand_verify_tar_file "$file" "$cmd" || return 1
|
||||
nand_verify_tar_file "$file" "$gz" || return 1
|
||||
else
|
||||
nand_verify_if_gzip_file "$file" "$cmd" || return 1
|
||||
nand_verify_if_gzip_file "$file" "$gz" || return 1
|
||||
if [ "$file_type" != "fit" -a "$file_type" != "ubi" -a "$file_type" != "ubifs" ]; then
|
||||
echo "invalid sysupgrade file"
|
||||
return 1
|
||||
|
||||
@@ -4,37 +4,29 @@
|
||||
. /lib/functions/system.sh
|
||||
. /usr/share/libubox/jshn.sh
|
||||
|
||||
# File-local constants
|
||||
CONF_TAR=/tmp/sysupgrade.tgz
|
||||
ETCBACKUP_DIR=/etc/backup
|
||||
INSTALLED_PACKAGES=${ETCBACKUP_DIR}/installed_packages.txt
|
||||
COMMAND=/lib/upgrade/do_stage2
|
||||
|
||||
# File-local globals
|
||||
ADD_PROVISIONING=0
|
||||
SAVE_OVERLAY=0
|
||||
SAVE_OVERLAY_PATH=
|
||||
SAVE_PARTITIONS=1
|
||||
SAVE_INSTALLED_PKGS=0
|
||||
SKIP_UNCHANGED=0
|
||||
CONF_IMAGE=
|
||||
CONF_BACKUP_LIST=0
|
||||
CONF_BACKUP=
|
||||
CONF_RESTORE=
|
||||
USE_CURR_PART=0
|
||||
NEED_IMAGE=
|
||||
HELP=0
|
||||
TEST=0
|
||||
|
||||
# Globals accessed in other files
|
||||
# initialize defaults
|
||||
export MTD_ARGS=""
|
||||
export MTD_CONFIG_ARGS=""
|
||||
export INTERACTIVE=0
|
||||
export VERBOSE=1
|
||||
export SAVE_CONFIG=1
|
||||
export SAVE_OVERLAY=0
|
||||
export SAVE_OVERLAY_PATH=
|
||||
export SAVE_PARTITIONS=1
|
||||
export SAVE_INSTALLED_PKGS=0
|
||||
export SKIP_UNCHANGED=0
|
||||
export CONF_IMAGE=
|
||||
export CONF_BACKUP_LIST=0
|
||||
export CONF_BACKUP=
|
||||
export CONF_RESTORE=
|
||||
export IGNORE_MINOR_COMPAT=0
|
||||
export NEED_IMAGE=
|
||||
export HELP=0
|
||||
export FORCE=0
|
||||
export CONFFILES=/tmp/sysupgrade.conffiles
|
||||
export TEST=0
|
||||
export USE_CURR_PART=0
|
||||
export ADD_PROVISIONING=0
|
||||
export UMOUNT_ETCBACKUP_DIR=0
|
||||
|
||||
# parse options
|
||||
while [ -n "$1" ]; do
|
||||
@@ -43,20 +35,20 @@ while [ -n "$1" ]; do
|
||||
-v) export VERBOSE="$(($VERBOSE + 1))";;
|
||||
-q) export VERBOSE="$(($VERBOSE - 1))";;
|
||||
-n) export SAVE_CONFIG=0;;
|
||||
-c) SAVE_OVERLAY=1 SAVE_OVERLAY_PATH=/etc;;
|
||||
-o) SAVE_OVERLAY=1 SAVE_OVERLAY_PATH=/;;
|
||||
-p) SAVE_PARTITIONS=0;;
|
||||
-P) ADD_PROVISIONING=1;;
|
||||
-k) SAVE_INSTALLED_PKGS=1;;
|
||||
-u) SKIP_UNCHANGED=1;;
|
||||
-b|--create-backup) CONF_BACKUP="$2" NEED_IMAGE=1; shift;;
|
||||
-r|--restore-backup) CONF_RESTORE="$2" NEED_IMAGE=1; shift;;
|
||||
-l|--list-backup) CONF_BACKUP_LIST=1;;
|
||||
-f) CONF_IMAGE="$2"; shift;;
|
||||
-s) USE_CURR_PART=1;;
|
||||
-c) export SAVE_OVERLAY=1 SAVE_OVERLAY_PATH=/etc;;
|
||||
-o) export SAVE_OVERLAY=1 SAVE_OVERLAY_PATH=/;;
|
||||
-p) export SAVE_PARTITIONS=0;;
|
||||
-P) export ADD_PROVISIONING=1;;
|
||||
-k) export SAVE_INSTALLED_PKGS=1;;
|
||||
-u) export SKIP_UNCHANGED=1;;
|
||||
-b|--create-backup) export CONF_BACKUP="$2" NEED_IMAGE=1; shift;;
|
||||
-r|--restore-backup) export CONF_RESTORE="$2" NEED_IMAGE=1; shift;;
|
||||
-l|--list-backup) export CONF_BACKUP_LIST=1;;
|
||||
-f) export CONF_IMAGE="$2"; shift;;
|
||||
-s) export USE_CURR_PART=1;;
|
||||
-F|--force) export FORCE=1;;
|
||||
-T|--test) TEST=1;;
|
||||
-h|--help) HELP=1; break;;
|
||||
-T|--test) export TEST=1;;
|
||||
-h|--help) export HELP=1; break;;
|
||||
--ignore-minor-compat-version) export IGNORE_MINOR_COMPAT=1;;
|
||||
-*)
|
||||
echo "Invalid option: $1" >&2
|
||||
@@ -67,6 +59,11 @@ while [ -n "$1" ]; do
|
||||
shift;
|
||||
done
|
||||
|
||||
export CONFFILES=/tmp/sysupgrade.conffiles
|
||||
export CONF_TAR=/tmp/sysupgrade.tgz
|
||||
export ETCBACKUP_DIR=/etc/backup
|
||||
export INSTALLED_PACKAGES=${ETCBACKUP_DIR}/installed_packages.txt
|
||||
|
||||
print_help() {
|
||||
cat <<EOF
|
||||
Usage: $0 [<upgrade-option>...] <image file or URL>
|
||||
@@ -137,20 +134,12 @@ fi
|
||||
|
||||
|
||||
list_conffiles() {
|
||||
if [ -f /usr/lib/opkg/status ]; then
|
||||
awk '
|
||||
BEGIN { conffiles = 0 }
|
||||
/^Conffiles:/ { conffiles = 1; next }
|
||||
!/^ / { conffiles = 0; next }
|
||||
conffiles == 1 { print }
|
||||
' /usr/lib/opkg/status
|
||||
elif [ -d /lib/apk/packages ]; then
|
||||
conffiles=""
|
||||
for file in /lib/apk/packages/*.conffiles_static; do
|
||||
conffiles="$(echo -e "$(cat $file)\n$conffiles")"
|
||||
done
|
||||
echo "$conffiles"
|
||||
fi
|
||||
awk '
|
||||
BEGIN { conffiles = 0 }
|
||||
/^Conffiles:/ { conffiles = 1; next }
|
||||
!/^ / { conffiles = 0; next }
|
||||
conffiles == 1 { print }
|
||||
' /usr/lib/opkg/status
|
||||
}
|
||||
|
||||
list_changed_conffiles() {
|
||||
@@ -249,77 +238,53 @@ fi
|
||||
|
||||
include /lib/upgrade
|
||||
|
||||
create_backup_archive() {
|
||||
do_save_conffiles() {
|
||||
local conf_tar="$1"
|
||||
local disabled
|
||||
local err
|
||||
|
||||
[ "$(rootfs_type)" = "tmpfs" ] && {
|
||||
echo "Cannot save config while running from ramdisk." >&2
|
||||
ask_bool 0 "Abort" && exit
|
||||
rm -f "$conf_tar"
|
||||
return 0
|
||||
}
|
||||
run_hooks "$CONFFILES" $sysupgrade_init_conffiles
|
||||
ask_bool 0 "Edit config file list" && vi "$CONFFILES"
|
||||
|
||||
[ "$conf_tar" != "-" ] || conf_tar=""
|
||||
if [ "$SAVE_INSTALLED_PKGS" -eq 1 ]; then
|
||||
echo "${INSTALLED_PACKAGES}" >> "$CONFFILES"
|
||||
mkdir -p "$ETCBACKUP_DIR"
|
||||
# Avoid touching filesystem on each backup
|
||||
RAMFS="$(mktemp -d -t sysupgrade.XXXXXX)"
|
||||
mkdir -p "$RAMFS/upper" "$RAMFS/work"
|
||||
mount -t overlay overlay -o lowerdir=$ETCBACKUP_DIR,upperdir=$RAMFS/upper,workdir=$RAMFS/work $ETCBACKUP_DIR &&
|
||||
UMOUNT_ETCBACKUP_DIR=1 || {
|
||||
echo "Cannot mount '$ETCBACKUP_DIR' as tmpfs to avoid touching disk while saving the list of installed packages." >&2
|
||||
ask_bool 0 "Abort" && exit
|
||||
}
|
||||
|
||||
# Format: pkg-name<TAB>{rom,overlay,unkown}
|
||||
# rom is used for pkgs in /rom, even if updated later
|
||||
find /usr/lib/opkg/info -name "*.control" \( \
|
||||
\( -exec test -f /rom/{} \; -exec echo {} rom \; \) -o \
|
||||
\( -exec test -f /overlay/upper/{} \; -exec echo {} overlay \; \) -o \
|
||||
\( -exec echo {} unknown \; \) \
|
||||
\) | sed -e 's,.*/,,;s/\.control /\t/' > ${INSTALLED_PACKAGES}
|
||||
fi
|
||||
|
||||
v "Saving config files..."
|
||||
[ "$VERBOSE" -gt 1 ] && TAR_V="v" || TAR_V=""
|
||||
sed -i -e 's,^/,,' "$CONFFILES"
|
||||
set -o pipefail
|
||||
{
|
||||
local ret=0
|
||||
|
||||
if [ $ret -eq 0 ]; then
|
||||
for service in /etc/init.d/*; do
|
||||
if ! $service enabled >/dev/null 2>&1; then
|
||||
disabled="$disabled$service disable\n"
|
||||
fi
|
||||
done
|
||||
disabled="$disabled\nexit 0"
|
||||
tar_print_member "/etc/uci-defaults/10_disable_services" "$(echo -e $disabled)" "$(date -r /etc/rc.d "+%s")" || ret=1
|
||||
fi
|
||||
|
||||
# Part of archive with installed packages info
|
||||
if [ $ret -eq 0 ]; then
|
||||
if [ "$SAVE_INSTALLED_PKGS" -eq 1 ]; then
|
||||
# Format: pkg-name<TAB>{rom,overlay,unknown}
|
||||
# rom is used for pkgs in /rom, even if updated later
|
||||
if [ -d "/usr/lib/opkg/info" ]; then
|
||||
tar_print_member "$INSTALLED_PACKAGES" "$(find /usr/lib/opkg/info -name "*.control" \( \
|
||||
\( -exec test -f /rom/{} \; -exec echo {} rom \; \) -o \
|
||||
\( -exec test -f /overlay/upper/{} \; -exec echo {} overlay \; \) -o \
|
||||
\( -exec echo {} unknown \; \) \
|
||||
\) | sed -e 's,.*/,,;s/\.control /\t/')" || ret=1
|
||||
elif [ -d "/lib/apk/packages" ]; then
|
||||
tar_print_member "$INSTALLED_PACKAGES" "$(find /lib/apk/packages -name "*.list" \( \
|
||||
\( -exec test -f /rom/{} \; -exec echo {} rom \; \) -o \
|
||||
\( -exec test -f /overlay/upper/{} \; -exec echo {} overlay \; \) -o \
|
||||
\( -exec echo {} unknown \; \) \
|
||||
\) | sed -e 's,.*/,,;s/\.list /\t/')" || ret=1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Rest of archive with config files and ending padding
|
||||
if [ $ret -eq 0 ]; then
|
||||
tar c${TAR_V} -C / -T "$CONFFILES" || ret=1
|
||||
fi
|
||||
|
||||
[ $ret -eq 0 ]
|
||||
} | gzip > "${conf_tar:-/proc/self/fd/1}"
|
||||
err=$?
|
||||
set +o pipefail
|
||||
|
||||
if [ "$err" -ne 0 ]; then
|
||||
tar c${TAR_V}zf "$conf_tar" -T "$CONFFILES" 2>/dev/null
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo "Failed to create the configuration backup."
|
||||
[ -f "$conf_tar" ] && rm -f "$conf_tar"
|
||||
rm -f "$conf_tar"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
[ "$UMOUNT_ETCBACKUP_DIR" -eq 1 ] && {
|
||||
umount "$ETCBACKUP_DIR"
|
||||
rm -rf "$RAMFS"
|
||||
}
|
||||
rm -f "$CONFFILES"
|
||||
|
||||
return "$err"
|
||||
}
|
||||
|
||||
if [ $CONF_BACKUP_LIST -eq 1 ]; then
|
||||
@@ -331,8 +296,8 @@ if [ $CONF_BACKUP_LIST -eq 1 ]; then
|
||||
fi
|
||||
|
||||
if [ -n "$CONF_BACKUP" ]; then
|
||||
create_backup_archive "$CONF_BACKUP"
|
||||
exit
|
||||
do_save_conffiles "$CONF_BACKUP"
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [ -n "$CONF_RESTORE" ]; then
|
||||
@@ -343,11 +308,7 @@ if [ -n "$CONF_RESTORE" ]; then
|
||||
|
||||
[ "$VERBOSE" -gt 1 ] && TAR_V="v" || TAR_V=""
|
||||
v "Restoring config files..."
|
||||
if [ "$(type -t platform_restore_backup)" == 'platform_restore_backup' ]; then
|
||||
platform_restore_backup "$TAR_V"
|
||||
else
|
||||
tar -C / -x${TAR_V}zf "$CONF_RESTORE"
|
||||
fi
|
||||
tar -C / -x${TAR_V}zf "$CONF_RESTORE"
|
||||
exit $?
|
||||
fi
|
||||
|
||||
@@ -406,7 +367,7 @@ if [ -n "$CONF_IMAGE" ]; then
|
||||
get_image "$CONF_IMAGE" "cat" > "$CONF_TAR"
|
||||
export SAVE_CONFIG=1
|
||||
elif ask_bool $SAVE_CONFIG "Keep config files over reflash"; then
|
||||
[ $TEST -eq 1 ] || create_backup_archive "$CONF_TAR" || exit
|
||||
[ $TEST -eq 1 ] || do_save_conffiles "$CONF_TAR"
|
||||
export SAVE_CONFIG=1
|
||||
else
|
||||
[ $TEST -eq 1 ] || rm -f "$CONF_TAR"
|
||||
@@ -420,6 +381,8 @@ fi
|
||||
install_bin /sbin/upgraded
|
||||
v "Commencing upgrade. Closing all shell sessions."
|
||||
|
||||
COMMAND='/lib/upgrade/do_stage2'
|
||||
|
||||
if [ -n "$FAILSAFE" ]; then
|
||||
printf '%s\x00%s\x00%s' "$RAM_ROOT" "$IMAGE" "$COMMAND" >/tmp/sysupgrade
|
||||
lock -u /tmp/.failsafe
|
||||
|
||||
271
lede/package/base-files/files/sbin/wifi
Executable file
271
lede/package/base-files/files/sbin/wifi
Executable file
@@ -0,0 +1,271 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2006 OpenWrt.org
|
||||
|
||||
. /lib/functions.sh
|
||||
. /usr/share/libubox/jshn.sh
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $0 [config|up|down|reconf|reload|status|isup]
|
||||
enables (default), disables or configures devices not yet configured.
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
ubus_wifi_cmd() {
|
||||
local cmd="$1"
|
||||
local dev="$2"
|
||||
|
||||
json_init
|
||||
[ -n "$2" ] && json_add_string device "$2"
|
||||
ubus call network.wireless "$1" "$(json_dump)"
|
||||
}
|
||||
|
||||
wifi_isup() {
|
||||
local dev="$1"
|
||||
|
||||
json_load "$(ubus_wifi_cmd "status" "$dev")"
|
||||
json_get_keys devices
|
||||
|
||||
for device in $devices; do
|
||||
json_select "$device"
|
||||
json_get_var up up
|
||||
[ $up -eq 0 ] && return 1
|
||||
json_select ..
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
find_net_config() {(
|
||||
local vif="$1"
|
||||
local cfg
|
||||
local ifname
|
||||
|
||||
config_get cfg "$vif" network
|
||||
|
||||
[ -z "$cfg" ] && {
|
||||
include /lib/network
|
||||
scan_interfaces
|
||||
|
||||
config_get ifname "$vif" ifname
|
||||
|
||||
cfg="$(find_config "$ifname")"
|
||||
}
|
||||
[ -z "$cfg" ] && return 0
|
||||
echo "$cfg"
|
||||
)}
|
||||
|
||||
|
||||
bridge_interface() {(
|
||||
local cfg="$1"
|
||||
[ -z "$cfg" ] && return 0
|
||||
|
||||
include /lib/network
|
||||
scan_interfaces
|
||||
|
||||
for cfg in $cfg; do
|
||||
config_get iftype "$cfg" type
|
||||
[ "$iftype" = bridge ] && config_get "$cfg" ifname
|
||||
prepare_interface_bridge "$cfg"
|
||||
return $?
|
||||
done
|
||||
)}
|
||||
|
||||
prepare_key_wep() {
|
||||
local key="$1"
|
||||
local hex=1
|
||||
|
||||
echo -n "$key" | grep -qE "[^a-fA-F0-9]" && hex=0
|
||||
[ "${#key}" -eq 10 -a $hex -eq 1 ] || \
|
||||
[ "${#key}" -eq 26 -a $hex -eq 1 ] || {
|
||||
[ "${key:0:2}" = "s:" ] && key="${key#s:}"
|
||||
key="$(echo -n "$key" | hexdump -ve '1/1 "%02x" ""')"
|
||||
}
|
||||
echo "$key"
|
||||
}
|
||||
|
||||
wifi_fixup_hwmode() {
|
||||
local device="$1"
|
||||
local default="$2"
|
||||
local hwmode hwmode_11n
|
||||
|
||||
config_get channel "$device" channel
|
||||
config_get hwmode "$device" hwmode
|
||||
case "$hwmode" in
|
||||
11bg) hwmode=bg;;
|
||||
11a) hwmode=a;;
|
||||
11ad) hwmode=ad;;
|
||||
11b) hwmode=b;;
|
||||
11g) hwmode=g;;
|
||||
11n*)
|
||||
hwmode_11n="${hwmode##11n}"
|
||||
case "$hwmode_11n" in
|
||||
a|g) ;;
|
||||
default) hwmode_11n="$default"
|
||||
esac
|
||||
config_set "$device" hwmode_11n "$hwmode_11n"
|
||||
;;
|
||||
*)
|
||||
hwmode=
|
||||
if [ "${channel:-0}" -gt 0 ]; then
|
||||
if [ "${channel:-0}" -gt 14 ]; then
|
||||
hwmode=a
|
||||
else
|
||||
hwmode=g
|
||||
fi
|
||||
else
|
||||
hwmode="$default"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
config_set "$device" hwmode "$hwmode"
|
||||
}
|
||||
|
||||
_wifi_updown() {
|
||||
for device in ${2:-$DEVICES}; do (
|
||||
config_get disabled "$device" disabled
|
||||
[ "$disabled" = "1" ] && {
|
||||
echo "'$device' is disabled"
|
||||
set disable
|
||||
}
|
||||
config_get iftype "$device" type
|
||||
if eval "type ${1}_$iftype" 2>/dev/null >/dev/null; then
|
||||
eval "scan_$iftype '$device'"
|
||||
eval "${1}_$iftype '$device'" || echo "$device($iftype): ${1} failed"
|
||||
elif [ ! -f /lib/netifd/wireless/$iftype.sh ]; then
|
||||
echo "$device($iftype): Interface type not supported"
|
||||
fi
|
||||
); done
|
||||
}
|
||||
|
||||
wifi_updown() {
|
||||
cmd=down
|
||||
[ enable = "$1" ] && {
|
||||
_wifi_updown disable "$2"
|
||||
ubus_wifi_cmd "$cmd" "$2"
|
||||
ubus call network reload
|
||||
scan_wifi
|
||||
cmd=up
|
||||
}
|
||||
[ reconf = "$1" ] && {
|
||||
ubus call network reload
|
||||
scan_wifi
|
||||
cmd=reconf
|
||||
}
|
||||
ubus_wifi_cmd "$cmd" "$2"
|
||||
_wifi_updown "$@"
|
||||
}
|
||||
|
||||
wifi_reload_legacy() {
|
||||
_wifi_updown "disable" "$1"
|
||||
scan_wifi
|
||||
_wifi_updown "enable" "$1"
|
||||
}
|
||||
|
||||
wifi_reload() {
|
||||
ubus call network reload
|
||||
wifi_reload_legacy
|
||||
}
|
||||
|
||||
wifi_detect_notice() {
|
||||
>&2 echo "WARNING: Wifi detect is deprecated. Use wifi config instead"
|
||||
>&2 echo "For more information, see commit 5f8f8a366136a07df661e31decce2458357c167a"
|
||||
exit 1
|
||||
}
|
||||
|
||||
wifi_config() {
|
||||
[ ! -f /etc/config/wireless ] && touch /etc/config/wireless
|
||||
|
||||
for driver in $DRIVERS; do (
|
||||
if eval "type detect_$driver" 2>/dev/null >/dev/null; then
|
||||
eval "detect_$driver" || echo "$driver: Detect failed" >&2
|
||||
else
|
||||
echo "$driver: Hardware detection not supported" >&2
|
||||
fi
|
||||
); done
|
||||
}
|
||||
|
||||
start_net() {(
|
||||
local iface="$1"
|
||||
local config="$2"
|
||||
local vifmac="$3"
|
||||
|
||||
[ -f "/var/run/$iface.pid" ] && kill "$(cat /var/run/${iface}.pid)" 2>/dev/null
|
||||
[ -z "$config" ] || {
|
||||
include /lib/network
|
||||
scan_interfaces
|
||||
for config in $config; do
|
||||
setup_interface "$iface" "$config" "" "$vifmac"
|
||||
done
|
||||
}
|
||||
)}
|
||||
|
||||
set_wifi_up() {
|
||||
local cfg="$1"
|
||||
local ifname="$2"
|
||||
uci_set_state wireless "$cfg" up 1
|
||||
uci_set_state wireless "$cfg" ifname "$ifname"
|
||||
}
|
||||
|
||||
set_wifi_down() {
|
||||
local cfg="$1"
|
||||
local vifs vif vifstr
|
||||
|
||||
[ -f "/var/run/wifi-${cfg}.pid" ] &&
|
||||
kill "$(cat "/var/run/wifi-${cfg}.pid")" 2>/dev/null
|
||||
uci_revert_state wireless "$cfg"
|
||||
config_get vifs "$cfg" vifs
|
||||
for vif in $vifs; do
|
||||
uci_revert_state wireless "$vif"
|
||||
done
|
||||
}
|
||||
|
||||
scan_wifi() {
|
||||
local cfgfile="$1"
|
||||
DEVICES=
|
||||
config_cb() {
|
||||
local type="$1"
|
||||
local section="$2"
|
||||
|
||||
# section start
|
||||
case "$type" in
|
||||
wifi-device)
|
||||
append DEVICES "$section"
|
||||
config_set "$section" vifs ""
|
||||
config_set "$section" ht_capab ""
|
||||
;;
|
||||
esac
|
||||
|
||||
# section end
|
||||
config_get TYPE "$CONFIG_SECTION" TYPE
|
||||
case "$TYPE" in
|
||||
wifi-iface)
|
||||
config_get device "$CONFIG_SECTION" device
|
||||
config_get vifs "$device" vifs
|
||||
append vifs "$CONFIG_SECTION"
|
||||
config_set "$device" vifs "$vifs"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
config_load "${cfgfile:-wireless}"
|
||||
}
|
||||
|
||||
DEVICES=
|
||||
DRIVERS=
|
||||
include /lib/wifi
|
||||
scan_wifi
|
||||
|
||||
case "$1" in
|
||||
down) wifi_updown "disable" "$2";;
|
||||
detect) wifi_detect_notice ;;
|
||||
config) wifi_config ;;
|
||||
status) ubus_wifi_cmd "status" "$2";;
|
||||
isup) wifi_isup "$2"; exit $?;;
|
||||
reload) wifi_reload "$2";;
|
||||
reload_legacy) wifi_reload_legacy "$2";;
|
||||
--help|help) usage;;
|
||||
reconf) wifi_updown "reconf" "$2";;
|
||||
''|up) wifi_updown "enable" "$2";;
|
||||
*) usage; exit 1;;
|
||||
esac
|
||||
@@ -1,17 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ -t 0 ] && {
|
||||
tty_dev=$(readlink /proc/self/fd/0)
|
||||
case "$tty_dev" in
|
||||
/dev/console|/dev/tty[0-9]*)
|
||||
export TERM=${TERM:-linux}
|
||||
;;
|
||||
/dev/*)
|
||||
export TERM=vt102
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
[ "$(uci -q get system.@system[0].ttylogin)" = 1 ] || exec /bin/login -f root
|
||||
[ "$(uci -q get system.@system[0].ttylogin)" = 1 ] || exec /bin/ash --login
|
||||
|
||||
exec /bin/login
|
||||
|
||||
@@ -56,17 +56,7 @@ json_init
|
||||
# Call platform_check_image() here so it can add its test
|
||||
# results and still mark image properly.
|
||||
json_set_namespace $old_ns
|
||||
platform_check_image "$1" >&2
|
||||
case "$?" in
|
||||
0)
|
||||
;;
|
||||
74)
|
||||
notify_firmware_broken
|
||||
;;
|
||||
*)
|
||||
notify_firmware_invalid
|
||||
;;
|
||||
esac
|
||||
platform_check_image "$1" >&2 || notify_firmware_invalid
|
||||
json_set_namespace validate_firmware_image old_ns
|
||||
json_close_object
|
||||
json_add_boolean valid "$VALID"
|
||||
|
||||
@@ -44,7 +44,7 @@ config TARGET_PREINIT_DISABLE_FAILSAFE
|
||||
config TARGET_PREINIT_TIMEOUT
|
||||
int
|
||||
prompt "Failsafe/Debug wait timeout" if PREINITOPT
|
||||
default 4
|
||||
default 2
|
||||
help
|
||||
How long to wait for failsafe mode to be entered or for
|
||||
a debug option to be pressed before continuing with a
|
||||
@@ -241,12 +241,6 @@ if VERSIONOPT
|
||||
help
|
||||
This an URL to provide users seeking support
|
||||
|
||||
config VERSION_FIRMWARE_URL
|
||||
string
|
||||
prompt "Firmware URL"
|
||||
help
|
||||
This is an URL to provide users for downloading firmware
|
||||
|
||||
config VERSION_PRODUCT
|
||||
string
|
||||
prompt "Product name"
|
||||
|
||||
@@ -40,7 +40,7 @@ endef
|
||||
define KernelPackage/brcm-wl/Default
|
||||
$(call Package/broadcom-wl/Default)
|
||||
SECTION:=kernel
|
||||
DEPENDS:=@(TARGET_bcm47xx||TARGET_bcm63xx) +wireless-tools +wifi-scripts +@KERNEL_WIRELESS_EXT
|
||||
DEPENDS:=@(TARGET_bcm47xx||TARGET_bcm63xx) +wireless-tools
|
||||
TITLE:=Kernel driver for BCM43xx chipsets
|
||||
FILES:=$(PKG_BUILD_DIR)/driver$(1)/wl.ko $(PKG_BUILD_DIR)/glue/wl_glue.ko
|
||||
AUTOLOAD:=$(call AutoProbe,wl)
|
||||
|
||||
@@ -95,13 +95,12 @@ include ralink.mk
|
||||
include realtek.mk
|
||||
|
||||
PKG_CONFIG_DEPENDS += \
|
||||
CONFIG_WIFI_SCRIPTS_UCODE \
|
||||
$(patsubst %,CONFIG_PACKAGE_kmod-%,$(PKG_DRIVERS))
|
||||
|
||||
define KernelPackage/cfg80211
|
||||
$(call KernelPackage/mac80211/Default)
|
||||
TITLE:=cfg80211 - wireless configuration API
|
||||
DEPENDS+= +iw +!WIFI_SCRIPTS_UCODE:iwinfo +wifi-scripts +wireless-regdb +USE_RFKILL:kmod-rfkill
|
||||
DEPENDS+= +iw +iwinfo +wireless-regdb +USE_RFKILL:kmod-rfkill
|
||||
ABI_VERSION:=$(PKG_VERSION)-$(PKG_RELEASE)
|
||||
FILES:= \
|
||||
$(PKG_BUILD_DIR)/compat/compat.ko \
|
||||
@@ -395,6 +394,14 @@ define Build/InstallDev
|
||||
endef
|
||||
|
||||
|
||||
define KernelPackage/cfg80211/install
|
||||
$(INSTALL_DIR) $(1)/lib/wifi $(1)/lib/netifd/wireless
|
||||
$(INSTALL_DATA) ./files/lib/wifi/mac80211.sh $(1)/lib/wifi
|
||||
$(INSTALL_BIN) ./files/lib/netifd/wireless/mac80211.sh $(1)/lib/netifd/wireless
|
||||
$(INSTALL_DIR) $(1)/etc/hotplug.d/ieee80211
|
||||
$(INSTALL_DATA) ./files/mac80211.hotplug $(1)/etc/hotplug.d/ieee80211/10-wifi-detect
|
||||
endef
|
||||
|
||||
$(eval $(foreach drv,$(PKG_DRIVERS),$(call KernelPackage,$(drv))))
|
||||
$(eval $(call KernelPackage,cfg80211))
|
||||
$(eval $(call KernelPackage,mac80211))
|
||||
|
||||
@@ -393,9 +393,9 @@ define KernelPackage/ath12k
|
||||
$(call KernelPackage/mac80211/Default)
|
||||
TITLE:=Qualcomm 802.11be wireless chipset support
|
||||
URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath12k
|
||||
DEPENDS+= @PCI_SUPPORT +kmod-ath +@DRIVER_11AC_SUPPORT +@DRIVER_11AX_SUPPORT \
|
||||
+kmod-crypto-michael-mic +kmod-qrtr-mhi \
|
||||
+kmod-qcom-qmi-helpers
|
||||
DEPENDS+= @PCI_SUPPORT +kmod-ath +kmod-crypto-michael-mic \
|
||||
+kmod-qrtr-mhi +kmod-qcom-qmi-helpers +@DRIVER_11AC_SUPPORT \
|
||||
+@DRIVER_11AX_SUPPORT +@DRIVER_11BE_SUPPORT
|
||||
FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath12k/ath12k.ko
|
||||
AUTOLOAD:=$(call AutoProbe,ath12k)
|
||||
endef
|
||||
|
||||
@@ -157,77 +157,79 @@ mac80211_hostapd_setup_base() {
|
||||
chan_ofs=0
|
||||
[ "$band" = "6g" ] && chan_ofs=1
|
||||
|
||||
ieee80211n=1
|
||||
ht_capab=
|
||||
case "$htmode" in
|
||||
VHT20|HT20|HE20) ;;
|
||||
HT40*|VHT40|VHT80|VHT160|HE40|HE80|HE160)
|
||||
case "$hwmode" in
|
||||
a)
|
||||
case "$(( (($channel / 4) + $chan_ofs) % 2 ))" in
|
||||
1) ht_capab="[HT40+]";;
|
||||
0) ht_capab="[HT40-]";;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
case "$htmode" in
|
||||
HT40+) ht_capab="[HT40+]";;
|
||||
HT40-) ht_capab="[HT40-]";;
|
||||
*)
|
||||
if [ "$channel" -lt 7 ]; then
|
||||
ht_capab="[HT40+]"
|
||||
else
|
||||
ht_capab="[HT40-]"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
[ "$auto_channel" -gt 0 ] && ht_capab="[HT40+]"
|
||||
;;
|
||||
*) ieee80211n= ;;
|
||||
esac
|
||||
if [ "$band" != "6g" ]; then
|
||||
ieee80211n=1
|
||||
ht_capab=
|
||||
case "$htmode" in
|
||||
VHT20|HT20|HE20|EHT20) ;;
|
||||
HT40*|VHT40|VHT80|VHT160|HE40|HE80|HE160|EHT40|EHT80|EHT160)
|
||||
case "$hwmode" in
|
||||
a)
|
||||
case "$(( (($channel / 4) + $chan_ofs) % 2 ))" in
|
||||
1) ht_capab="[HT40+]";;
|
||||
0) ht_capab="[HT40-]";;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
case "$htmode" in
|
||||
HT40+) ht_capab="[HT40+]";;
|
||||
HT40-) ht_capab="[HT40-]";;
|
||||
*)
|
||||
if [ "$channel" -lt 7 ]; then
|
||||
ht_capab="[HT40+]"
|
||||
else
|
||||
ht_capab="[HT40-]"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
[ "$auto_channel" -gt 0 ] && ht_capab="[HT40+]"
|
||||
;;
|
||||
*) ieee80211n= ;;
|
||||
esac
|
||||
|
||||
[ -n "$ieee80211n" ] && {
|
||||
append base_cfg "ieee80211n=1" "$N"
|
||||
[ -n "$ieee80211n" ] && {
|
||||
append base_cfg "ieee80211n=1" "$N"
|
||||
|
||||
set_default ht_coex 0
|
||||
append base_cfg "ht_coex=$ht_coex" "$N"
|
||||
set_default ht_coex 0
|
||||
append base_cfg "ht_coex=$ht_coex" "$N"
|
||||
|
||||
json_get_vars \
|
||||
ldpc:1 \
|
||||
greenfield:0 \
|
||||
short_gi_20:1 \
|
||||
short_gi_40:1 \
|
||||
tx_stbc:1 \
|
||||
rx_stbc:3 \
|
||||
max_amsdu:1 \
|
||||
dsss_cck_40:1
|
||||
json_get_vars \
|
||||
ldpc:1 \
|
||||
greenfield:0 \
|
||||
short_gi_20:1 \
|
||||
short_gi_40:1 \
|
||||
tx_stbc:1 \
|
||||
rx_stbc:3 \
|
||||
max_amsdu:1 \
|
||||
dsss_cck_40:1
|
||||
|
||||
ht_cap_mask=0
|
||||
for cap in $(iw phy "$phy" info | grep -E '^\s*Capabilities:' | cut -d: -f2); do
|
||||
ht_cap_mask="$(($ht_cap_mask | $cap))"
|
||||
done
|
||||
ht_cap_mask=0
|
||||
for cap in $(iw phy "$phy" info | grep -E '^\s*Capabilities:' | cut -d: -f2); do
|
||||
ht_cap_mask="$(($ht_cap_mask | $cap))"
|
||||
done
|
||||
|
||||
cap_rx_stbc=$((($ht_cap_mask >> 8) & 3))
|
||||
[ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc"
|
||||
ht_cap_mask="$(( ($ht_cap_mask & ~(0x300)) | ($cap_rx_stbc << 8) ))"
|
||||
cap_rx_stbc=$((($ht_cap_mask >> 8) & 3))
|
||||
[ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc"
|
||||
ht_cap_mask="$(( ($ht_cap_mask & ~(0x300)) | ($cap_rx_stbc << 8) ))"
|
||||
|
||||
mac80211_add_capabilities ht_capab_flags $ht_cap_mask \
|
||||
LDPC:0x1::$ldpc \
|
||||
GF:0x10::$greenfield \
|
||||
SHORT-GI-20:0x20::$short_gi_20 \
|
||||
SHORT-GI-40:0x40::$short_gi_40 \
|
||||
TX-STBC:0x80::$tx_stbc \
|
||||
RX-STBC1:0x300:0x100:1 \
|
||||
RX-STBC12:0x300:0x200:1 \
|
||||
RX-STBC123:0x300:0x300:1 \
|
||||
MAX-AMSDU-7935:0x800::$max_amsdu \
|
||||
DSSS_CCK-40:0x1000::$dsss_cck_40
|
||||
mac80211_add_capabilities ht_capab_flags $ht_cap_mask \
|
||||
LDPC:0x1::$ldpc \
|
||||
GF:0x10::$greenfield \
|
||||
SHORT-GI-20:0x20::$short_gi_20 \
|
||||
SHORT-GI-40:0x40::$short_gi_40 \
|
||||
TX-STBC:0x80::$tx_stbc \
|
||||
RX-STBC1:0x300:0x100:1 \
|
||||
RX-STBC12:0x300:0x200:1 \
|
||||
RX-STBC123:0x300:0x300:1 \
|
||||
MAX-AMSDU-7935:0x800::$max_amsdu \
|
||||
DSSS_CCK-40:0x1000::$dsss_cck_40
|
||||
|
||||
ht_capab="$ht_capab$ht_capab_flags"
|
||||
[ -n "$ht_capab" ] && append base_cfg "ht_capab=$ht_capab" "$N"
|
||||
}
|
||||
ht_capab="$ht_capab$ht_capab_flags"
|
||||
[ -n "$ht_capab" ] && append base_cfg "ht_capab=$ht_capab" "$N"
|
||||
}
|
||||
fi
|
||||
|
||||
# 802.11ac
|
||||
enable_ac=0
|
||||
@@ -236,8 +238,8 @@ mac80211_hostapd_setup_base() {
|
||||
|
||||
idx="$channel"
|
||||
case "$htmode" in
|
||||
VHT20|HE20) enable_ac=1;;
|
||||
VHT40|HE40)
|
||||
VHT20|HE20|EHT20) enable_ac=1;;
|
||||
VHT40|HE40|EHT40)
|
||||
case "$(( (($channel / 4) + $chan_ofs) % 2 ))" in
|
||||
1) idx=$(($channel + 2));;
|
||||
0) idx=$(($channel - 2));;
|
||||
@@ -245,7 +247,7 @@ mac80211_hostapd_setup_base() {
|
||||
enable_ac=1
|
||||
vht_center_seg0=$idx
|
||||
;;
|
||||
VHT80|HE80)
|
||||
VHT80|HE80|EHT80)
|
||||
case "$(( (($channel / 4) + $chan_ofs) % 4 ))" in
|
||||
1) idx=$(($channel + 6));;
|
||||
2) idx=$(($channel + 2));;
|
||||
@@ -256,7 +258,7 @@ mac80211_hostapd_setup_base() {
|
||||
vht_oper_chwidth=1
|
||||
vht_center_seg0=$idx
|
||||
;;
|
||||
VHT160|HE160)
|
||||
VHT160|HE160|EHT160|EHT320)
|
||||
if [ "$band" = "6g" ]; then
|
||||
case "$channel" in
|
||||
1|5|9|13|17|21|25|29) idx=15;;
|
||||
@@ -284,15 +286,32 @@ mac80211_hostapd_setup_base() {
|
||||
|
||||
[ "$background_radar" -eq 1 ] && append base_cfg "enable_background_radar=1" "$N"
|
||||
}
|
||||
|
||||
eht_oper_chwidth=$vht_oper_chwidth
|
||||
eht_center_seg0=$vht_center_seg0
|
||||
|
||||
[ "$band" = "6g" ] && {
|
||||
op_class=
|
||||
case "$htmode" in
|
||||
HE20) op_class=131;;
|
||||
HE*) op_class=$((132 + $vht_oper_chwidth))
|
||||
HE20|EHT20) op_class=131;;
|
||||
EHT320)
|
||||
case "$channel" in
|
||||
1|5|9|13|17|21|25|29|33|37|41|45|49|53|57|61) idx=31;;
|
||||
65|69|73|77|81|85|89|93|97|101|105|109|113|117|121|125) idx=95;;
|
||||
129|133|137|141|145|149|153|157|161|165|169|173|177|181|185|189) idx=159;;
|
||||
193|197|201|205|209|213|217|221) idx=191;;
|
||||
esac
|
||||
|
||||
op_class=137
|
||||
eht_center_seg0=$idx
|
||||
eht_oper_chwidth=9
|
||||
;;
|
||||
HE*|EHT*) op_class=$((132 + $vht_oper_chwidth));;
|
||||
esac
|
||||
[ -n "$op_class" ] && append base_cfg "op_class=$op_class" "$N"
|
||||
}
|
||||
[ "$hwmode" = "a" ] || enable_ac=0
|
||||
[ "$band" = "6g" ] && enable_ac=0
|
||||
|
||||
if [ "$enable_ac" != "0" -o "$vendor_vht" = "1" ]; then
|
||||
json_get_vars \
|
||||
@@ -415,8 +434,10 @@ mac80211_hostapd_setup_base() {
|
||||
|
||||
# 802.11ax
|
||||
enable_ax=0
|
||||
enable_be=0
|
||||
case "$htmode" in
|
||||
HE*) enable_ax=1 ;;
|
||||
EHT*) enable_ax=1; enable_be=1 ;;
|
||||
esac
|
||||
|
||||
if [ "$enable_ax" != "0" ]; then
|
||||
@@ -490,6 +511,14 @@ mac80211_hostapd_setup_base() {
|
||||
append base_cfg "he_mu_edca_ac_vo_timer=255" "$N"
|
||||
fi
|
||||
|
||||
if [ "$enable_be" != "0" ]; then
|
||||
append base_cfg "ieee80211be=1" "$N"
|
||||
[ "$hwmode" = "a" ] && {
|
||||
append base_cfg "eht_oper_chwidth=$eht_oper_chwidth" "$N"
|
||||
append base_cfg "eht_oper_centr_freq_seg0_idx=$eht_center_seg0" "$N"
|
||||
}
|
||||
fi
|
||||
|
||||
hostapd_prepare_device_config "$hostapd_conf_file" nl80211
|
||||
cat >> "$hostapd_conf_file" <<EOF
|
||||
${channel:+channel=$channel}
|
||||
@@ -1111,7 +1140,6 @@ drv_mac80211_setup() {
|
||||
|
||||
hostapd_conf_file="/var/run/hostapd-$phy.conf"
|
||||
|
||||
no_ap=1
|
||||
macidx=0
|
||||
staidx=0
|
||||
|
||||
|
||||
@@ -64,8 +64,7 @@ define KernelPackage/mt76-default
|
||||
DEPENDS:= \
|
||||
+kmod-mac80211 \
|
||||
+@DRIVER_11AC_SUPPORT \
|
||||
+@KERNEL_PAGE_POOL \
|
||||
@!TARGET_uml
|
||||
+@KERNEL_PAGE_POOL
|
||||
endef
|
||||
|
||||
define KernelPackage/mt76
|
||||
@@ -342,8 +341,8 @@ endef
|
||||
define KernelPackage/mt7996e
|
||||
$(KernelPackage/mt76-default)
|
||||
TITLE:=MediaTek MT7996E wireless driver
|
||||
DEPENDS+=@PCI_SUPPORT +kmod-mt76-connac +kmod-hwmon-core +@DRIVER_11AX_SUPPORT \
|
||||
+@KERNEL_RELAY +@DRIVER_11BE_SUPPORT
|
||||
DEPENDS+=@PCI_SUPPORT +kmod-mt76-connac +kmod-hwmon-core \
|
||||
+@KERNEL_RELAY +@DRIVER_11AX_SUPPORT +@DRIVER_11BE_SUPPORT
|
||||
FILES:= $(PKG_BUILD_DIR)/mt7996/mt7996e.ko
|
||||
AUTOLOAD:=$(call AutoProbe,mt7996e)
|
||||
endef
|
||||
@@ -388,7 +387,7 @@ define KernelPackage/mt7925-common
|
||||
$(KernelPackage/mt76-default)
|
||||
TITLE:=MediaTek MT7925 wireless driver common code
|
||||
HIDDEN:=1
|
||||
DEPENDS+=+kmod-mt792x-common +@DRIVER_11AX_SUPPORT +kmod-hwmon-core +@DRIVER_11BE_SUPPORT
|
||||
DEPENDS+=+kmod-mt792x-common +@DRIVER_11AX_SUPPORT +kmod-hwmon-core
|
||||
FILES:= $(PKG_BUILD_DIR)/mt7925/mt7925-common.ko
|
||||
endef
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ sed -i 's/services/nas/g' /usr/lib/lua/luci/view/minidlna_status.htm
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/share/luci/menu.d/luci-app-samba4.json
|
||||
|
||||
sed -i 's#downloads.openwrt.org#mirrors.tencent.com/lede#g' /etc/opkg/distfeeds.conf
|
||||
sed -i 's#downloads.openwrt.org#mirrors.tencent.com/lede#g' /etc/apk/repositories.d/distfeeds.list
|
||||
sed -i 's/root::0:0:99999:7:::/root:$1$V4UetPzk$CYXluq4wUazHjmCDBCqXF.:0:0:99999:7:::/g' /etc/shadow
|
||||
sed -i 's/root:::0:99999:7:::/root:$1$V4UetPzk$CYXluq4wUazHjmCDBCqXF.:0:0:99999:7:::/g' /etc/shadow
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/libnl-tiny.git
|
||||
PKG_SOURCE_DATE:=2025-10-03
|
||||
PKG_SOURCE_VERSION:=feca1d341d4baa9579ec62762672aa0f20edf564
|
||||
PKG_MIRROR_HASH:=6362b51a2413684a259fb57847adad4ba934578a7e2c0c2cc5360e931115de21
|
||||
PKG_SOURCE_DATE:=2025-03-19
|
||||
PKG_SOURCE_VERSION:=c0df580adbd4d555ecc1962dbe88e91d75b67a4e
|
||||
PKG_MIRROR_HASH:=e0a723e791549866e2d7e1f2aec2392343186645a2c7eae97e73e9fa72171d96
|
||||
CMAKE_INSTALL:=1
|
||||
|
||||
PKG_LICENSE:=LGPL-2.1
|
||||
|
||||
@@ -5,9 +5,9 @@ PKG_RELEASE=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/uclient.git
|
||||
PKG_MIRROR_HASH:=7c443cac02a734dd312c65618f4de17248d188317f30a9fac192c1503b3d5c05
|
||||
PKG_SOURCE_DATE:=2021-05-14
|
||||
PKG_SOURCE_VERSION:=6a6011df3429ffa5958d12b1327eeda4fd9daa47
|
||||
PKG_MIRROR_HASH:=339b58bd6d6f4b56bb5b0d41c9b47fdad6a7211a2a2eb264a62de3e07fcedfad
|
||||
PKG_SOURCE_DATE:=2024-10-22
|
||||
PKG_SOURCE_VERSION:=88ae8f208dd313f69e268234f7db55956aef1cb9
|
||||
CMAKE_INSTALL:=1
|
||||
|
||||
PKG_BUILD_DEPENDS:=ustream-ssl
|
||||
@@ -16,6 +16,7 @@ PKG_LICENSE:=ISC
|
||||
PKG_LICENSE_FILES:=
|
||||
|
||||
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
||||
PKG_CONFIG_DEPENDS := CONFIG_PACKAGE_ucode-mod-uclient
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
@@ -37,6 +38,16 @@ define Package/uclient-fetch
|
||||
DEPENDS:=+libuclient
|
||||
endef
|
||||
|
||||
define Package/ucode-mod-uclient
|
||||
SECTION:=utils
|
||||
CATEGORY:=Utilities
|
||||
TITLE:=ucode uclient module
|
||||
DEPENDS:=+libucode +libuclient
|
||||
endef
|
||||
|
||||
CMAKE_OPTIONS += \
|
||||
-DBUILD_UCODE=$(if $(CONFIG_PACKAGE_ucode-mod-uclient),ON,OFF)
|
||||
|
||||
define Package/libuclient/install
|
||||
$(INSTALL_DIR) $(1)/usr/lib
|
||||
$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libuclient.so $(1)/usr/lib/
|
||||
@@ -47,5 +58,11 @@ define Package/uclient-fetch/install
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/uclient-fetch $(1)/bin/
|
||||
endef
|
||||
|
||||
define Package/ucode-mod-uclient/install
|
||||
$(INSTALL_DIR) $(1)/usr/lib/ucode
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/*.so $(1)/usr/lib/ucode
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,libuclient))
|
||||
$(eval $(call BuildPackage,uclient-fetch))
|
||||
$(eval $(call BuildPackage,ucode-mod-uclient))
|
||||
|
||||
@@ -11,9 +11,9 @@ PKG_NAME:=udebug
|
||||
CMAKE_INSTALL:=1
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/udebug.git
|
||||
PKG_MIRROR_HASH:=553a58a14b59dc7b22755557acbc74f0655a431442a4faca56d28cdb1ef14fb4
|
||||
PKG_SOURCE_DATE:=2023-12-06
|
||||
PKG_SOURCE_VERSION:=6d3f51f9fda706f0cf4732c762e4dbe8c21e12cf
|
||||
PKG_MIRROR_HASH:=6a056e6ed77bf0a7af74fcbac9cdd10bbc51868eea054da8a2d18ef1e3c4abca
|
||||
PKG_SOURCE_DATE:=2025-08-24
|
||||
PKG_SOURCE_VERSION:=edeb4d6dc690acb476a47e6b11633b5632b08437
|
||||
PKG_ABI_VERSION:=$(call abi_version_str,$(PKG_SOURCE_DATE))
|
||||
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
@@ -51,7 +51,7 @@ define Package/udebug-cli
|
||||
SECTION:=utils
|
||||
CATEGORY:=Utilities
|
||||
TITLE:=OpenWrt debug service CLI
|
||||
DEPENDS:=+udebugd +ucode-mod-udebug
|
||||
DEPENDS:=+udebugd +ucode-mod-udebug +ucode-mod-uloop +ucode-mod-ubus
|
||||
endef
|
||||
|
||||
define Package/libudebug/install
|
||||
|
||||
@@ -5,9 +5,9 @@ PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/ustream-ssl.git
|
||||
PKG_SOURCE_DATE:=2022-12-08
|
||||
PKG_SOURCE_VERSION:=9217ab46536353c7c792951b57163063f5ec7a3b
|
||||
PKG_MIRROR_HASH:=cd4dc6a6c18290348b1f8b1c01df3320e4954dc46d714c797bef066f7a91248d
|
||||
PKG_SOURCE_DATE:=2024-07-28
|
||||
PKG_SOURCE_VERSION:=99bd3d2b167ccdffb6de072d02c380cb37b23e33
|
||||
PKG_MIRROR_HASH:=9165ce1b05e7bf5ab2cd8450da30c980f1996c9d3a97c4ed2a573b282467b839
|
||||
CMAKE_INSTALL:=1
|
||||
|
||||
PKG_LICENSE:=ISC
|
||||
|
||||
@@ -20,7 +20,6 @@ PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_REAL_
|
||||
|
||||
PKG_FIXUP:=libtool libtool-abiver
|
||||
PKG_INSTALL:=1
|
||||
PKG_USE_MIPS16:=0
|
||||
PKG_BUILD_FLAGS:=no-mips16 lto
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
PKG_LICENSE:=GPL-2.0-or-later
|
||||
|
||||
@@ -5,9 +5,9 @@ PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git
|
||||
PKG_SOURCE_DATE:=2025-10-06
|
||||
PKG_SOURCE_VERSION:=649028013a3c8f6ed53fc97ca997d2528d06b5d9
|
||||
PKG_MIRROR_HASH:=4399542c79dbb6860748d3e5746b003bc56061374a4f4de7bdde80fa803bbc0d
|
||||
PKG_SOURCE_DATE:=2021-06-04
|
||||
PKG_SOURCE_VERSION:=50381d0a2998f6c0fc4823f0c2aa4206063d549e
|
||||
PKG_MIRROR_HASH:=2718df3d3538c93ac77accf55716fb341741df3d231aac59e04dd1f80f558889
|
||||
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
@@ -21,8 +21,7 @@ include $(INCLUDE_DIR)/cmake.mk
|
||||
define Package/netifd
|
||||
SECTION:=base
|
||||
CATEGORY:=Base system
|
||||
DEPENDS:=+libuci +libnl-tiny +libubus +ubus +ubusd +jshn +libubox +libudebug \
|
||||
+ucode +ucode-mod-fs +ucode-mod-ubus +ucode-mod-uloop +ucode-mod-uci
|
||||
DEPENDS:=+libuci +libnl-tiny +libubus +ubus +ubusd +jshn +libubox
|
||||
TITLE:=OpenWrt Network Interface Configuration Daemon
|
||||
endef
|
||||
|
||||
@@ -44,10 +43,7 @@ define Package/netifd/install
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/netifd $(1)/sbin/
|
||||
$(CP) ./files/* $(1)/
|
||||
$(INSTALL_DIR) $(1)/etc/udhcpc.user.d/
|
||||
$(CP) \
|
||||
$(PKG_BUILD_DIR)/scripts/utils.sh \
|
||||
$(PKG_BUILD_DIR)/scripts/netifd-proto.sh \
|
||||
$(1)/lib/netifd/
|
||||
$(CP) $(PKG_BUILD_DIR)/scripts/* $(1)/lib/netifd/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,netifd))
|
||||
|
||||
@@ -30,11 +30,12 @@ reload_service() {
|
||||
|
||||
init_switch
|
||||
ubus call network reload || rv=1
|
||||
/sbin/wifi reload_legacy
|
||||
return $rv
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
[ -x /sbin/wifi ] && /sbin/wifi down
|
||||
/sbin/wifi down
|
||||
ifdown -a
|
||||
sleep 1
|
||||
}
|
||||
|
||||
@@ -14,12 +14,5 @@ service_triggers() {
|
||||
}
|
||||
|
||||
reload_service() {
|
||||
packet_steering="$(uci -q get "network.@globals[0].packet_steering")"
|
||||
steering_flows="$(uci -q get "network.@globals[0].steering_flows")"
|
||||
[ "${steering_flows:-0}" -gt 0 ] && opts="-l $steering_flows"
|
||||
if [ -e "/usr/libexec/platform/packet-steering.sh" ]; then
|
||||
/usr/libexec/platform/packet-steering.sh "$packet_steering"
|
||||
else
|
||||
/usr/libexec/network/packet-steering.uc $opts "$packet_steering"
|
||||
fi
|
||||
/usr/libexec/network/packet-steering.sh
|
||||
}
|
||||
|
||||
@@ -18,13 +18,13 @@ setup_interface () {
|
||||
proto_add_ipv4_address "$ip" "${subnet:-255.255.255.0}"
|
||||
# TODO: apply $broadcast
|
||||
|
||||
local ip_net IP PREFIX NETWORK NETMASK BROADCAST
|
||||
ipcalc "$ip/$mask" && ip_net="$NETWORK"
|
||||
local ip_net
|
||||
eval "$(ipcalc.sh "$ip/$mask")";ip_net="$NETWORK"
|
||||
|
||||
local i
|
||||
for i in $router; do
|
||||
local gw_net
|
||||
ipcalc "$i/$mask" && gw_net="$NETWORK"
|
||||
eval "$(ipcalc.sh "$i/$mask")";gw_net="$NETWORK"
|
||||
|
||||
[ "$ip_net" != "$gw_net" ] && proto_add_ipv4_route "$i" 32 "" "$ip"
|
||||
proto_add_ipv4_route 0.0.0.0 0 "$i" "$ip"
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
import * as uci from "uci";
|
||||
import * as uloop from "uloop";
|
||||
import * as ubus from "ubus";
|
||||
import { access, dirname } from "fs";
|
||||
|
||||
function ex_handler(e)
|
||||
{
|
||||
netifd.log(netifd.L_WARNING, `Exception: ${e}\n${e.stacktrace[0].context}\n`);
|
||||
}
|
||||
|
||||
uloop.guard(ex_handler);
|
||||
ubus.guard(ex_handler);
|
||||
|
||||
let wireless;
|
||||
|
||||
function uci_ctx()
|
||||
{
|
||||
let savedir = netifd.dummy_mode ? "./tmp" : null;
|
||||
let ctx = uci.cursor(netifd.config_path, savedir, null, {
|
||||
strict: false
|
||||
});
|
||||
return ctx;
|
||||
}
|
||||
|
||||
function config_init()
|
||||
{
|
||||
let ctx = uci_ctx();
|
||||
|
||||
if (wireless)
|
||||
wireless.config_init(ctx);
|
||||
}
|
||||
|
||||
function config_start()
|
||||
{
|
||||
if (wireless)
|
||||
wireless.config_start();
|
||||
}
|
||||
|
||||
function check_interfaces()
|
||||
{
|
||||
if (wireless)
|
||||
wireless.check_interfaces();
|
||||
}
|
||||
|
||||
function hotplug(name, add)
|
||||
{
|
||||
if (wireless)
|
||||
wireless.hotplug(name, add);
|
||||
}
|
||||
|
||||
function ex_wrap(cb)
|
||||
{
|
||||
let fn = cb;
|
||||
return (...args) => {
|
||||
try {
|
||||
return fn(...args);
|
||||
} catch (e) {
|
||||
netifd.log(netifd.L_WARNING, `${e}\n${e.stacktrace[0].context}`);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
netifd.cb = {
|
||||
hotplug: ex_wrap(hotplug),
|
||||
config_init: ex_wrap(config_init),
|
||||
config_start: ex_wrap(config_start),
|
||||
check_interfaces: ex_wrap(check_interfaces),
|
||||
};
|
||||
|
||||
const wireless_module = dirname(sourcepath()) + "/wireless.uc";
|
||||
if (access(wireless_module, "r")) {
|
||||
try {
|
||||
wireless = loadfile(wireless_module)();
|
||||
} catch (e) {
|
||||
netifd.log(netifd.L_WARNING, `Error loading wireless module: ${e}\n${e.stacktrace[0].context}\n`);
|
||||
}
|
||||
} else {
|
||||
netifd.log(netifd.L_WARNING, `Wireless module not found\n`);
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ -x /sbin/udhcpc ] || exit 0
|
||||
[ -L /sbin/udhcpc ] || exit 0
|
||||
|
||||
. /lib/functions.sh
|
||||
. ../netifd-proto.sh
|
||||
. /lib/config/uci.sh
|
||||
init_proto "$@"
|
||||
|
||||
proto_dhcp_init_config() {
|
||||
@@ -32,18 +31,6 @@ proto_dhcp_add_sendopts() {
|
||||
[ -n "$1" ] && append "$3" "-x $1"
|
||||
}
|
||||
|
||||
proto_dhcp_get_default_clientid() {
|
||||
[ -z "$1" ] && return
|
||||
|
||||
local iface="$1"
|
||||
local duid
|
||||
local iaid="0"
|
||||
|
||||
[ -e "/sys/class/net/$iface/ifindex" ] && iaid="$(cat "/sys/class/net/$iface/ifindex")"
|
||||
duid="$(uci_get network @globals[0] dhcp_default_duid)"
|
||||
[ -n "$duid" ] && printf "ff%08x%s" "$iaid" "$duid"
|
||||
}
|
||||
|
||||
proto_dhcp_setup() {
|
||||
local config="$1"
|
||||
local iface="$2"
|
||||
@@ -64,8 +51,7 @@ proto_dhcp_setup() {
|
||||
[ "$defaultreqopts" = 0 ] && defaultreqopts="-o" || defaultreqopts=
|
||||
[ "$broadcast" = 1 ] && broadcast="-B" || broadcast=
|
||||
[ "$norelease" = 1 ] && norelease="" || norelease="-R"
|
||||
[ -z "$clientid" ] && clientid="$(proto_dhcp_get_default_clientid "$iface")"
|
||||
[ -n "$clientid" ] && clientid="-x 0x3d:${clientid//:/}"
|
||||
[ -n "$clientid" ] && clientid="-x 0x3d:${clientid//:/}" || clientid="-C"
|
||||
[ -n "$iface6rd" ] && proto_export "IFACE6RD=$iface6rd"
|
||||
[ "$iface6rd" != 0 -a -f /lib/netifd/proto/6rd.sh ] && append dhcpopts "-O 212"
|
||||
[ -n "$zone6rd" ] && proto_export "ZONE6RD=$zone6rd"
|
||||
@@ -81,7 +67,7 @@ proto_dhcp_setup() {
|
||||
-p /var/run/udhcpc-$iface.pid \
|
||||
-s /lib/netifd/dhcp.script \
|
||||
-f -t 0 -i "$iface" \
|
||||
${ipaddr:+-r ${ipaddr/\/*/}} \
|
||||
${ipaddr:+-r $ipaddr} \
|
||||
${hostname:+-x "hostname:$hostname"} \
|
||||
${vendorid:+-V "$vendorid"} \
|
||||
$clientid $defaultreqopts $broadcast $norelease $dhcpopts
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import { glob, basename, realpath, chdir, mkstemp } from "fs";
|
||||
|
||||
export const TYPE_ARRAY = 1;
|
||||
export const TYPE_STRING = 3;
|
||||
export const TYPE_INT = 5;
|
||||
export const TYPE_BOOL = 7;
|
||||
|
||||
export function parse_bool(val)
|
||||
{
|
||||
switch (val) {
|
||||
case "1":
|
||||
case "true":
|
||||
return true;
|
||||
case "0":
|
||||
case "false":
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export function parse_array(val)
|
||||
{
|
||||
if (type(val) != "array")
|
||||
val = split(val, /\s+/);
|
||||
return val;
|
||||
};
|
||||
|
||||
function __type_parsers()
|
||||
{
|
||||
let ret = [];
|
||||
|
||||
ret[TYPE_ARRAY] = parse_array;
|
||||
ret[TYPE_STRING] = function(val) {
|
||||
return val;
|
||||
};
|
||||
ret[TYPE_INT] = function(val) {
|
||||
return +val;
|
||||
};
|
||||
ret[TYPE_BOOL] = parse_bool;
|
||||
|
||||
return ret;
|
||||
}
|
||||
export const type_parser = __type_parsers();
|
||||
|
||||
export function handler_load(path, cb)
|
||||
{
|
||||
for (let script in glob(path + "/*.sh")) {
|
||||
script = basename(script);
|
||||
|
||||
let f = mkstemp();
|
||||
let prev_dir = realpath(".");
|
||||
chdir(path);
|
||||
system(`./${script} "" "dump" >&${f.fileno()}`);
|
||||
chdir(prev_dir);
|
||||
f.seek();
|
||||
while (!f.error()) {
|
||||
let data = trim(f.read("line"));
|
||||
try {
|
||||
data = json(data);
|
||||
} catch (e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type(data) != "object")
|
||||
continue;
|
||||
|
||||
cb(script, data);
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
};
|
||||
|
||||
export function handler_attributes(data, extra, validate)
|
||||
{
|
||||
let ret = { ...extra };
|
||||
for (let cur in data) {
|
||||
let name_data = split(cur[0], ":", 2);
|
||||
let name = name_data[0];
|
||||
ret[name] = cur[1];
|
||||
if (validate && name_data[1])
|
||||
validate[name] = name_data[1];
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
export function parse_attribute_list(data, spec)
|
||||
{
|
||||
let ret = {};
|
||||
|
||||
for (let name, type_id in spec) {
|
||||
if (!(name in data))
|
||||
continue;
|
||||
|
||||
let val = data[name];
|
||||
let parser = type_parser[type_id];
|
||||
if (parser)
|
||||
val = parser(val);
|
||||
ret[name] = val;
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
export function is_equal(val1, val2) {
|
||||
let t1 = type(val1);
|
||||
|
||||
if (t1 != type(val2))
|
||||
return false;
|
||||
|
||||
if (t1 == "array") {
|
||||
if (length(val1) != length(val2))
|
||||
return false;
|
||||
|
||||
for (let i = 0; i < length(val1); i++)
|
||||
if (!is_equal(val1[i], val2[i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
} else if (t1 == "object") {
|
||||
for (let key in val1)
|
||||
if (!is_equal(val1[key], val2[key]))
|
||||
return false;
|
||||
for (let key in val2)
|
||||
if (val1[key] == null)
|
||||
return false;
|
||||
return true;
|
||||
} else {
|
||||
return val1 == val2;
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
ifup_all=
|
||||
setup_wifi=
|
||||
|
||||
if_call() {
|
||||
local interface="$1"
|
||||
@@ -13,6 +14,7 @@ case "$0" in
|
||||
*ifdown) modes=down;;
|
||||
*ifup)
|
||||
modes="down up"
|
||||
setup_wifi=1
|
||||
;;
|
||||
*) echo "Invalid command: $0";;
|
||||
esac
|
||||
@@ -23,6 +25,10 @@ while :; do
|
||||
ifup_all=1
|
||||
shift
|
||||
;;
|
||||
-w)
|
||||
setup_wifi=
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
@@ -34,6 +40,7 @@ if [ -n "$ifup_all" ]; then
|
||||
for interface in $(ubus -S list 'network.interface.*'); do
|
||||
if_call "${interface##network.interface.}"
|
||||
done
|
||||
[ -n "$setup_wifi" ] && /sbin/wifi up
|
||||
exit
|
||||
else
|
||||
ubus -S list "network.interface.$1" > /dev/null || {
|
||||
@@ -42,3 +49,29 @@ else
|
||||
}
|
||||
if_call "$1"
|
||||
fi
|
||||
|
||||
if [ -n "$setup_wifi" ] && grep -sq config /etc/config/wireless; then
|
||||
. /lib/functions.sh
|
||||
|
||||
find_related_radios() {
|
||||
local wdev wnet
|
||||
config_get wdev "$1" device
|
||||
config_get wnet "$1" network
|
||||
|
||||
if [ -n "$wdev" ]; then
|
||||
for wnet in $wnet; do
|
||||
if [ "$wnet" = "$network" ]; then
|
||||
append radio_devs "$wdev" "$N"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
network="$1"
|
||||
config_load wireless
|
||||
config_foreach find_related_radios wifi-iface
|
||||
|
||||
for dev in $(echo "$radio_devs" | sort -u); do
|
||||
/sbin/wifi up "$dev"
|
||||
done
|
||||
fi
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#!/bin/sh
|
||||
NPROCS="$(grep -c "^processor.*:" /proc/cpuinfo)"
|
||||
[ "$NPROCS" -gt 1 ] || exit
|
||||
|
||||
PROC_MASK="$(( (1 << $NPROCS) - 1 ))"
|
||||
|
||||
find_irq_cpu() {
|
||||
local dev="$1"
|
||||
local match="$(grep -m 1 "$dev\$" /proc/interrupts)"
|
||||
local cpu=0
|
||||
|
||||
[ -n "$match" ] && {
|
||||
set -- $match
|
||||
shift
|
||||
for cur in $(seq 1 $NPROCS); do
|
||||
[ "$1" -gt 0 ] && {
|
||||
cpu=$(($cur - 1))
|
||||
break
|
||||
}
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
echo "$cpu"
|
||||
}
|
||||
|
||||
set_hex_val() {
|
||||
local file="$1"
|
||||
local val="$2"
|
||||
val="$(printf %x "$val")"
|
||||
[ -n "$DEBUG" ] && echo "$file = $val"
|
||||
echo "$val" > "$file" 2>/dev/null
|
||||
}
|
||||
|
||||
packet_steering="$(uci get "network.@globals[0].packet_steering")"
|
||||
[ "$packet_steering" != 1 ] && exit 0
|
||||
|
||||
exec 512>/var/lock/smp_tune.lock
|
||||
flock 512 || exit 1
|
||||
|
||||
[ -e "/usr/libexec/platform/packet-steering.sh" ] && {
|
||||
/usr/libexec/platform/packet-steering.sh
|
||||
exit 0
|
||||
}
|
||||
|
||||
for dev in /sys/class/net/*; do
|
||||
[ -d "$dev" ] || continue
|
||||
|
||||
# ignore virtual interfaces
|
||||
[ -n "$(ls "${dev}/" | grep '^lower_')" ] && continue
|
||||
[ -d "${dev}/device" ] || continue
|
||||
|
||||
device="$(readlink "${dev}/device")"
|
||||
device="$(basename "$device")"
|
||||
irq_cpu="$(find_irq_cpu "$device")"
|
||||
irq_cpu_mask="$((1 << $irq_cpu))"
|
||||
|
||||
for q in ${dev}/queues/tx-*; do
|
||||
set_hex_val "$q/xps_cpus" "$PROC_MASK"
|
||||
done
|
||||
|
||||
# ignore dsa slave ports for RPS
|
||||
subsys="$(readlink "${dev}/device/subsystem")"
|
||||
subsys="$(basename "$subsys")"
|
||||
[ "$subsys" = "mdio_bus" ] && continue
|
||||
|
||||
for q in ${dev}/queues/rx-*; do
|
||||
set_hex_val "$q/rps_cpus" "$PROC_MASK"
|
||||
done
|
||||
done
|
||||
@@ -1,279 +0,0 @@
|
||||
#!/usr/bin/env ucode
|
||||
'use strict';
|
||||
import { glob, basename, dirname, readlink, readfile, realpath, writefile, error, open } from "fs";
|
||||
|
||||
let napi_weight = 1.0;
|
||||
let cpu_thread_weight = 0.75;
|
||||
let rx_weight = 0.75;
|
||||
let eth_bias = 2.0;
|
||||
let debug = 0, do_nothing = 0;
|
||||
let disable;
|
||||
let cpus;
|
||||
let all_cpus;
|
||||
let local_flows = 0;
|
||||
|
||||
while (length(ARGV) > 0) {
|
||||
let arg = shift(ARGV);
|
||||
switch (arg) {
|
||||
case "-d":
|
||||
debug++;
|
||||
break;
|
||||
case "-n":
|
||||
do_nothing++;
|
||||
break;
|
||||
case '0':
|
||||
disable = true;
|
||||
break;
|
||||
case '2':
|
||||
all_cpus = true;
|
||||
break;
|
||||
case '-l':
|
||||
local_flows = +shift(ARGV);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function task_name(pid)
|
||||
{
|
||||
let stat = open(`/proc/${pid}/status`, "r");
|
||||
if (!stat)
|
||||
return;
|
||||
let line = stat.read("line");
|
||||
stat.close();
|
||||
return trim(split(line, "\t", 2)[1]);
|
||||
}
|
||||
|
||||
function set_task_cpu(pid, cpu) {
|
||||
if (disable)
|
||||
cpu = join(",", map(cpus, (cpu) => cpu.id));
|
||||
let name = task_name(pid);
|
||||
if (!name)
|
||||
return;
|
||||
if (debug || do_nothing)
|
||||
warn(`taskset -p -c ${cpu} ${name}\n`);
|
||||
if (!do_nothing)
|
||||
system(`taskset -p -c ${cpu} ${pid}`);
|
||||
}
|
||||
|
||||
function cpu_mask(cpu)
|
||||
{
|
||||
let mask;
|
||||
if (cpu < 0)
|
||||
mask = (1 << length(cpus)) - 1;
|
||||
else
|
||||
mask = (1 << int(cpu));
|
||||
return sprintf("%x", mask);
|
||||
}
|
||||
|
||||
function set_netdev_cpu(dev, cpu, rx_queue) {
|
||||
rx_queue ??= "rx-*";
|
||||
let queues = glob(`/sys/class/net/${dev}/queues/${rx_queue}/rps_cpus`);
|
||||
let val = cpu_mask(cpu);
|
||||
if (disable)
|
||||
val = 0;
|
||||
for (let queue in queues) {
|
||||
if (debug || do_nothing)
|
||||
warn(`echo ${val} > ${queue}\n`);
|
||||
if (!do_nothing)
|
||||
writefile(queue, `${val}`);
|
||||
}
|
||||
queues = glob(`/sys/class/net/${dev}/queues/${rx_queue}/rps_flow_cnt`);
|
||||
for (let queue in queues) {
|
||||
if (debug || do_nothing)
|
||||
warn(`echo ${local_flows} > ${queue}\n`);
|
||||
if (!do_nothing)
|
||||
writefile(queue, `${local_flows}`);
|
||||
}
|
||||
}
|
||||
|
||||
function task_device_match(name, device)
|
||||
{
|
||||
let napi_match = match(name, /napi\/([^-]*)-\d+/);
|
||||
if (!napi_match)
|
||||
napi_match = match(name, /mt76-tx (phy\d+)/);
|
||||
if (napi_match &&
|
||||
(index(device.phy, napi_match[1]) >= 0 ||
|
||||
index(device.netdev, napi_match[1]) >= 0))
|
||||
return true;
|
||||
|
||||
if (device.driver == "mtk_soc_eth" && match(name, /napi\/mtk_eth-/))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
cpus = map(glob("/sys/bus/cpu/devices/*"), (path) => {
|
||||
return {
|
||||
id: int(match(path, /.*cpu(\d+)/)[1]),
|
||||
core: int(trim(readfile(`${path}/topology/core_id`))),
|
||||
load: 0.0,
|
||||
};
|
||||
});
|
||||
|
||||
cpus = slice(cpus, 0, 64);
|
||||
if (length(cpus) < 2)
|
||||
exit(0);
|
||||
|
||||
function cpu_add_weight(cpu_id, weight)
|
||||
{
|
||||
let cpu = cpus[cpu_id];
|
||||
cpu.load += weight;
|
||||
for (let sibling in cpus) {
|
||||
if (sibling == cpu || sibling.core != cpu.core)
|
||||
continue;
|
||||
sibling.load += weight * cpu_thread_weight;
|
||||
}
|
||||
}
|
||||
|
||||
function get_next_cpu(weight, prev_cpu)
|
||||
{
|
||||
if (disable)
|
||||
return 0;
|
||||
|
||||
let sort_cpus = sort(slice(cpus), (a, b) => a.load - b.load);
|
||||
let idx = 0;
|
||||
|
||||
if (prev_cpu != null && sort_cpus[idx].id == prev_cpu)
|
||||
idx++;
|
||||
|
||||
let cpu = sort_cpus[idx].id;
|
||||
cpu_add_weight(cpu, weight);
|
||||
return cpu;
|
||||
}
|
||||
|
||||
let phys_devs = {};
|
||||
let netdev_phys = {};
|
||||
let netdevs = map(glob("/sys/class/net/*"), (dev) => basename(dev));
|
||||
|
||||
for (let dev in netdevs) {
|
||||
let pdev_path = realpath(`/sys/class/net/${dev}/device`);
|
||||
if (!pdev_path)
|
||||
continue;
|
||||
|
||||
if (length(glob(`/sys/class/net/${dev}/lower_*`)) > 0)
|
||||
continue;
|
||||
|
||||
let pdev = phys_devs[pdev_path];
|
||||
if (!pdev) {
|
||||
pdev = phys_devs[pdev_path] = {
|
||||
path: pdev_path,
|
||||
driver: basename(readlink(`${pdev_path}/driver`)),
|
||||
netdev: [],
|
||||
phy: [],
|
||||
tasks: [],
|
||||
rx_tasks: [],
|
||||
rx_queues: map(glob(`/sys/class/net/${dev}/queues/rx-*/rps_cpus`),
|
||||
(v) => basename(dirname(v))),
|
||||
};
|
||||
}
|
||||
|
||||
let phyidx = trim(readfile(`/sys/class/net/${dev}/phy80211/index`));
|
||||
if (phyidx != null) {
|
||||
let phy = `phy${phyidx}`;
|
||||
if (index(pdev.phy, phy) < 0)
|
||||
push(pdev.phy, phy);
|
||||
}
|
||||
|
||||
push(pdev.netdev, dev);
|
||||
netdev_phys[dev] = pdev;
|
||||
}
|
||||
|
||||
for (let path in glob("/proc/*/exe")) {
|
||||
readlink(path);
|
||||
if (error() != "No such file or directory")
|
||||
continue;
|
||||
|
||||
let pid = basename(dirname(path));
|
||||
let name = task_name(pid);
|
||||
for (let devname in phys_devs) {
|
||||
let dev = phys_devs[devname];
|
||||
if (!task_device_match(name, dev))
|
||||
continue;
|
||||
|
||||
push(dev.tasks, pid);
|
||||
|
||||
let napi_match = match(name, /napi\/([^-]*)-(\d+)/);
|
||||
if (napi_match && napi_match[2] > 0)
|
||||
push(dev.rx_tasks, pid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function assign_dev_queues_cpu(dev) {
|
||||
let num = length(dev.rx_queues);
|
||||
if (num < length(dev.rx_tasks))
|
||||
num = length(dev.rx_tasks);
|
||||
|
||||
for (let i = 0; i < num; i++) {
|
||||
let cpu;
|
||||
|
||||
let task = dev.rx_tasks[i];
|
||||
if (num >= length(cpus))
|
||||
cpu = i % length(cpus);
|
||||
else if (task)
|
||||
cpu = get_next_cpu(napi_weight);
|
||||
else
|
||||
cpu = -1;
|
||||
set_task_cpu(task, cpu);
|
||||
|
||||
let rxq = dev.rx_queues[i];
|
||||
if (!rxq)
|
||||
continue;
|
||||
|
||||
if (num >= length(cpus))
|
||||
cpu = (i + 1) % length(cpus);
|
||||
else if (all_cpus)
|
||||
cpu = -1;
|
||||
else
|
||||
cpu = get_next_cpu(napi_weight, cpu);
|
||||
for (let netdev in dev.netdev)
|
||||
set_netdev_cpu(netdev, cpu, rxq);
|
||||
}
|
||||
}
|
||||
|
||||
function assign_dev_cpu(dev) {
|
||||
if (length(dev.rx_queues) > 1 &&
|
||||
length(dev.rx_tasks) > 1)
|
||||
return assign_dev_queues_cpu(dev);
|
||||
|
||||
if (length(dev.tasks) > 0) {
|
||||
let cpu = dev.napi_cpu = get_next_cpu(napi_weight);
|
||||
for (let task in dev.tasks)
|
||||
set_task_cpu(task, cpu);
|
||||
}
|
||||
|
||||
if (length(dev.netdev) > 0) {
|
||||
let cpu;
|
||||
if (all_cpus)
|
||||
cpu = -1;
|
||||
else
|
||||
cpu = get_next_cpu(rx_weight, dev.napi_cpu);
|
||||
for (let netdev in dev.netdev)
|
||||
set_netdev_cpu(netdev, cpu);
|
||||
}
|
||||
}
|
||||
|
||||
// Assign ethernet devices first
|
||||
for (let devname in phys_devs) {
|
||||
let dev = phys_devs[devname];
|
||||
if (!length(dev.phy))
|
||||
assign_dev_cpu(dev);
|
||||
}
|
||||
|
||||
// Add bias to avoid assigning other tasks to CPUs with ethernet NAPI
|
||||
for (let devname in phys_devs) {
|
||||
let dev = phys_devs[devname];
|
||||
if (!length(dev.tasks) || dev.napi_cpu == null)
|
||||
continue;
|
||||
cpu_add_weight(dev.napi_cpu, eth_bias);
|
||||
}
|
||||
|
||||
// Assign WLAN devices
|
||||
for (let devname in phys_devs) {
|
||||
let dev = phys_devs[devname];
|
||||
if (length(dev.phy) > 0)
|
||||
assign_dev_cpu(dev);
|
||||
}
|
||||
|
||||
if (debug > 1)
|
||||
warn(sprintf("devices: %.J\ncpus: %.J\n", phys_devs, cpus));
|
||||
@@ -1,3 +0,0 @@
|
||||
config WIFI_SCRIPTS_UCODE
|
||||
bool "Use new ucode based scripts"
|
||||
default n
|
||||
@@ -1,53 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2024 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=wifi-scripts
|
||||
PKG_VERSION:=1.0
|
||||
PKG_RELEASE:=1
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
||||
PKG_CONFIG_DEPENDS:=CONFIG_WIFI_SCRIPTS_UCODE
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/wifi-scripts
|
||||
SECTION:=utils
|
||||
CATEGORY:=Base system
|
||||
DEPENDS:=+netifd +ucode +ucode-mod-nl80211 +ucode-mod-rtnl +ucode-mod-ubus +ucode-mod-uci +ucode-mod-digest
|
||||
TITLE:=Wi-Fi configuration scripts
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/wifi-scripts/config
|
||||
source "$(SOURCE)/Config.in"
|
||||
endef
|
||||
|
||||
define Package/wifi-scripts/description
|
||||
A set of scripts that handle setup and configuration of Wi-Fi devices.
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/wifi-scripts/install
|
||||
$(INSTALL_DIR) $(1)
|
||||
$(CP) ./files/* $(1)/
|
||||
ifeq ($(CONFIG_WIFI_SCRIPTS_UCODE),y)
|
||||
$(CP) ./files-ucode/* $(1)/
|
||||
endif
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,wifi-scripts))
|
||||
@@ -1,338 +0,0 @@
|
||||
#!/usr/bin/ucode
|
||||
|
||||
'use strict';
|
||||
|
||||
import { set_default, log } from 'wifi.common';
|
||||
import { validate, dump_options } from 'wifi.validate';
|
||||
import * as supplicant from 'wifi.supplicant';
|
||||
import * as hostapd from 'wifi.hostapd';
|
||||
import * as netifd from 'wifi.netifd';
|
||||
import * as iface from 'wifi.iface';
|
||||
import { find_phy } from 'wifi.utils';
|
||||
import * as nl80211 from 'nl80211';
|
||||
import * as fs from 'fs';
|
||||
|
||||
global.radio = ARGV[2];
|
||||
|
||||
const mesh_param_list = [
|
||||
"mesh_retry_timeout", "mesh_confirm_timeout", "mesh_holding_timeout", "mesh_max_peer_links",
|
||||
"mesh_max_retries", "mesh_ttl", "mesh_element_ttl", "mesh_hwmp_max_preq_retries",
|
||||
"mesh_path_refresh_time", "mesh_min_discovery_timeout", "mesh_hwmp_active_path_timeout",
|
||||
"mesh_hwmp_preq_min_interval", "mesh_hwmp_net_diameter_traversal_time", "mesh_hwmp_rootmode",
|
||||
"mesh_hwmp_rann_interval", "mesh_gate_announcements", "mesh_sync_offset_max_neighor",
|
||||
"mesh_rssi_threshold", "mesh_hwmp_active_path_to_root_timeout", "mesh_hwmp_root_interval",
|
||||
"mesh_hwmp_confirmation_interval", "mesh_awake_window", "mesh_plink_timeout",
|
||||
"mesh_auto_open_plinks", "mesh_fwding", "mesh_nolearn", "mesh_power_mode"
|
||||
];
|
||||
|
||||
function phy_suffix(radio, sep) {
|
||||
if (radio == null || radio < 0)
|
||||
return "";
|
||||
return sep + radio;
|
||||
}
|
||||
|
||||
function reset_config(phy, radio) {
|
||||
let name = phy + phy_suffix(radio, ".");
|
||||
let prev_config = `/var/run/hostapd-${name}.conf`;
|
||||
|
||||
global.ubus.call('hostapd', 'config_set', { phy, radio, config: '', prev_config });
|
||||
global.ubus.call('wpa_supplicant', 'config_set', { phy, radio, config: []});
|
||||
|
||||
name = phy + phy_suffix(radio, ":");
|
||||
system(`ucode /usr/share/hostap/wdev.uc ${name} set_config '{}'`);
|
||||
}
|
||||
|
||||
function get_channel_frequency(band, channel) {
|
||||
if (channel < 1)
|
||||
return null;
|
||||
|
||||
switch (band) {
|
||||
case '2g':
|
||||
if (channel == 14)
|
||||
return 2484;
|
||||
return 2407 + channel * 5;
|
||||
case '5g':
|
||||
if (channel >= 182 && channel <= 196)
|
||||
return 4000 + channel * 5;
|
||||
return 5000 + channel * 5;
|
||||
case '6g':
|
||||
if (channel == 2)
|
||||
return 5935;
|
||||
return 5950 + channel * 5;
|
||||
case '60g':
|
||||
return 56160 + channel * 2160;
|
||||
}
|
||||
}
|
||||
|
||||
function setup_phy(phy, config, data) {
|
||||
if (config.channel == "auto")
|
||||
config.channel = 0;
|
||||
config.channel = +config.channel;
|
||||
config.frequency = get_channel_frequency(config.band, config.channel);
|
||||
|
||||
if (config.country) {
|
||||
log(`Setting country code to ${config.country}`);
|
||||
system(`iw reg set ${config.country}`);
|
||||
}
|
||||
|
||||
set_default(config, 'rxantenna', 0xffffffff);
|
||||
set_default(config, 'txantenna', 0xffffffff);
|
||||
|
||||
if (config.txantenna == 'all')
|
||||
config.txantenna = 0xffffffff;
|
||||
if (config.rxantenna == 'all')
|
||||
config.rxantenna = 0xffffffff;
|
||||
|
||||
if (config.txantenna != data?.txantenna || config.rxantenna != data?.rxantenna)
|
||||
reset_config(phy, config.radio);
|
||||
|
||||
netifd.set_data({
|
||||
phy,
|
||||
radio: config.radio,
|
||||
txantenna: config.txantenna,
|
||||
rxantenna: config.rxantenna
|
||||
});
|
||||
|
||||
if (config.txpower)
|
||||
config.txpower = 'fixed ' + config.txpower + '00';
|
||||
else
|
||||
config.txpower = 'auto';
|
||||
|
||||
log(`Configuring '${phy}' txantenna: ${config.txantenna}, rxantenna: ${config.rxantenna} distance: ${config.distance}`);
|
||||
system(`iw phy ${phy} set antenna ${config.txantenna} ${config.rxantenna}`);
|
||||
system(`iw phy ${phy} set distance ${config.distance}`);
|
||||
system(`iw phy ${phy} set txpower ${config.txpower}`);
|
||||
|
||||
if (config.frag)
|
||||
system(`iw phy ${phy} set frag ${config.frag}`);
|
||||
if (config.rts)
|
||||
system(`iw phy ${phy} set rts ${config.rts}`);
|
||||
}
|
||||
|
||||
function iw_htmode(config) {
|
||||
let suffix = substr(config.htmode, 3);
|
||||
if (suffix == "40+" || suffix == "40-")
|
||||
return "HT" + suffix;
|
||||
|
||||
switch (config.htmode ?? "NONE") {
|
||||
case "HT20":
|
||||
case "VHT20":
|
||||
case "HE20":
|
||||
case "EHT20":
|
||||
return "HT20";
|
||||
case "VHT80":
|
||||
case "HE80":
|
||||
case "EHT80":
|
||||
case "HE160":
|
||||
case "EHT160":
|
||||
case "EHT320":
|
||||
return "80MHZ";
|
||||
case "NONE":
|
||||
case "NOHT":
|
||||
return "NOHT";
|
||||
}
|
||||
|
||||
if (substr(config.htmode, 2) == "40") {
|
||||
switch (config.band) {
|
||||
case "2g":
|
||||
if (+config.channel < 7)
|
||||
return "HT40+";
|
||||
else
|
||||
return "HT40-";
|
||||
default:
|
||||
return ((+config.channel / 4) % 2) ? "HT40+" : "HT40-";
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function config_add(config, name, val) {
|
||||
if (val != null)
|
||||
config[name] = val;
|
||||
}
|
||||
|
||||
function config_add_mesh_params(config, data) {
|
||||
for (let param in mesh_param_list)
|
||||
config_add(config, param, data[param]);
|
||||
}
|
||||
|
||||
function setup() {
|
||||
let data = json(ARGV[3]);
|
||||
|
||||
data.phy = find_phy(data.config, true);
|
||||
if (!data.phy) {
|
||||
log('Bug: PHY is undefined for device');
|
||||
netifd.set_retry(false);
|
||||
return 1;
|
||||
}
|
||||
data.phy_suffix = phy_suffix(data.config.radio, ":");
|
||||
data.vif_phy_suffix = phy_suffix(data.config.radio, ".");
|
||||
data.ifname_prefix = data.config.ifname_prefix;
|
||||
if (!data.ifname_prefix)
|
||||
data.ifname_prefix = data.phy + data.vif_phy_suffix + "-";
|
||||
let active_ifnames = [];
|
||||
|
||||
log('Starting');
|
||||
|
||||
let config = data.config;
|
||||
|
||||
if (!config.band) {
|
||||
switch (config.hwmode) {
|
||||
case 'a':
|
||||
case '11a':
|
||||
config.band = '5g';
|
||||
break;
|
||||
case 'ad':
|
||||
case '11ad':
|
||||
config.band = '60g';
|
||||
break;
|
||||
case 'b':
|
||||
case 'g':
|
||||
case '11b':
|
||||
case '11g':
|
||||
default:
|
||||
config.band = '2g';
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete config.hwmode;
|
||||
|
||||
validate('device', config);
|
||||
setup_phy(data.phy, data.config, data.data);
|
||||
|
||||
let supplicant_mesh;
|
||||
let has_ap = false;
|
||||
let idx = {};
|
||||
let supplicant_data = [];
|
||||
let wdev_data = {};
|
||||
|
||||
for (let k, v in data.interfaces) {
|
||||
let mode = v.config.mode;
|
||||
idx[mode] ??= 0;
|
||||
let mode_idx = idx[mode]++;
|
||||
|
||||
if (!v.config.ifname)
|
||||
v.config.ifname = data.ifname_prefix + mode + mode_idx;
|
||||
push(active_ifnames, v.config.ifname);
|
||||
|
||||
if (v.config.encryption == 'owe' && v.config.owe_transition) {
|
||||
mode_idx = idx[mode]++;
|
||||
v.config.owe_transition_ifname = data.ifname_prefix + mode + mode_idx;
|
||||
push(active_ifnames, v.config.ifname);
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case 'ap':
|
||||
has_ap = true;
|
||||
for (let _, sta in v.stas)
|
||||
validate('station', sta.config);
|
||||
// fallthrough
|
||||
case 'sta':
|
||||
case 'adhoc':
|
||||
case 'mesh':
|
||||
if (mode != "ap")
|
||||
data.config.noscan = true;
|
||||
validate('iface', v.config);
|
||||
iface.prepare(v.config, data.phy + data.phy_suffix, data.config.num_global_macaddr, data.config.macaddr_base);
|
||||
netifd.set_vif(k, v.config.ifname);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case 'adhoc':
|
||||
if (config.frequency && !v.config.wpa)
|
||||
break;
|
||||
// fallthrough
|
||||
case 'mesh':
|
||||
supplicant_mesh ??= !system("wpa_supplicant -vmesh");
|
||||
if (mode == "mesh" && !supplicant_mesh)
|
||||
break;
|
||||
// fallthrough
|
||||
case 'sta':
|
||||
data.ap_start_disabled = true;
|
||||
let config = supplicant.generate(supplicant_data, data, v);
|
||||
if (mode == "mesh")
|
||||
config_add_mesh_params(config, v.config);
|
||||
continue;
|
||||
case 'monitor':
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
// fallback to wdev setup
|
||||
let config = {
|
||||
mode,
|
||||
ssid: v.config.ssid,
|
||||
};
|
||||
|
||||
if (!v.config.default_macaddr)
|
||||
config.macaddr = v.config.macaddr;
|
||||
|
||||
config_add(config, "freq", data.config.frequency);
|
||||
config_add(config, "htmode", iw_htmode(data.config));
|
||||
if (mode != "monitor") {
|
||||
let basic_rate_list = v.config.basic_rate ?? data.config.basic_rate;
|
||||
config_add(config, "basic-rates", supplicant.ratelist(basic_rate_list));
|
||||
config_add(config, "mcast-rate", supplicant.ratestr(v.config.mcast_rate));
|
||||
config_add(config, "beacon-interval", data.config.beacon_int);
|
||||
if (mode == "adhoc")
|
||||
config_add(config, "bssid", v.config.bssid);
|
||||
if (mode == "mesh") {
|
||||
config_add(config, "ssid", v.config.mesh_id);
|
||||
config_add_mesh_params(config, v.config);
|
||||
}
|
||||
}
|
||||
|
||||
wdev_data[v.config.ifname] = config;
|
||||
}
|
||||
|
||||
supplicant.setup(supplicant_data, data);
|
||||
hostapd.setup(data);
|
||||
|
||||
system(`ucode /usr/share/hostap/wdev.uc ${data.phy}${data.phy_suffix} set_config '${printf("%J", wdev_data)}' ${join(' ', active_ifnames)}`);
|
||||
|
||||
if (length(supplicant_data) > 0)
|
||||
supplicant.start(data);
|
||||
|
||||
netifd.set_up();
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
function teardown() {
|
||||
let data = json(ARGV[3]);
|
||||
|
||||
if (ARGV[2] == "#mlo")
|
||||
return 0;
|
||||
|
||||
if (!data.data?.phy) {
|
||||
log('Bug: PHY is undefined for device');
|
||||
return 1;
|
||||
}
|
||||
|
||||
log(`Tearing down ${data.data.phy}`);
|
||||
|
||||
reset_config(data.data.phy, data.data.radio);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
let ret = 1;
|
||||
|
||||
switch(ARGV[1]) {
|
||||
case 'dump':
|
||||
ret = dump_options();
|
||||
break;
|
||||
|
||||
case 'setup':
|
||||
ret = setup();
|
||||
break;
|
||||
|
||||
case 'teardown':
|
||||
ret = teardown();
|
||||
break;
|
||||
}
|
||||
|
||||
exit(ret);
|
||||
@@ -1,191 +0,0 @@
|
||||
#!/usr/bin/ucode
|
||||
|
||||
'use strict';
|
||||
|
||||
import { find_phy } from 'wifi.utils';
|
||||
import * as uci from 'uci';
|
||||
import * as iwinfo from 'iwinfo';
|
||||
|
||||
function print_assoclist(stations) {
|
||||
for (let mac, station in stations) {
|
||||
printf(`${station.mac} ${station.signal} dBm / ${station.noise} dBm (SNR ${station.snr}) ${station.inactive_time} ms ago\n`);
|
||||
for (let k in [ 'rx', 'tx' ]) {
|
||||
let bitrate = station[k];
|
||||
let flags = join(', ', bitrate.flags);
|
||||
|
||||
printf(`\t${uc(k)}: ${bitrate.bitrate == 'unknown' ? 'unknown' : bitrate.bitrate + ' MBit/s'}`);
|
||||
if (length(bitrate.flags))
|
||||
printf(', %s', flags);
|
||||
printf('%10d Pkts.\n', bitrate.packets);
|
||||
}
|
||||
printf(`\texpected throughput: ${station.expected_throughput}\n\n`);
|
||||
}
|
||||
}
|
||||
|
||||
function print_countrylist(list) {
|
||||
for (let k, v in list.countries)
|
||||
printf(`${k == list.active ? '*' : ' '} ${k} "${v}"\n`);
|
||||
}
|
||||
|
||||
function print_freqlist(channels) {
|
||||
for (let channel in channels) {
|
||||
printf(`${channel.active ? '*' : ' '} ${channel.freq} GHz (Band: ${channel.band} GHz, Channel ${channel.channel})`);
|
||||
if (length(channel.flags))
|
||||
printf(` [${join(', ', channel.flags)}]`);
|
||||
printf('\n');
|
||||
}
|
||||
}
|
||||
|
||||
function print_htmodelist(htmode) {
|
||||
printf('%s\n', join(' ', htmode));
|
||||
}
|
||||
|
||||
function print_info(list) {
|
||||
let padding = ' ';
|
||||
|
||||
for (let bss in list) {
|
||||
printf(`${bss.iface} ESSID: ${bss.ssid === null ? 'unknown' : '"' + bss.ssid + '"'}\n`);
|
||||
printf(`${padding}Access Point: ${bss.mac}\n`);
|
||||
printf(`${padding}Mode: ${bss.mode} Channel: ${bss.channel} (${bss.freq} GHz) HT Mode: ${bss.htmode}\n`);
|
||||
printf(`${padding}Center Channel 1: ${bss.center_freq1} 2: ${bss.center_freq2}\n`);
|
||||
printf(`${padding}Tx-Power: ${bss.txpower} dBm Link Quality: ${bss.quality}/70\n`);
|
||||
printf(`${padding}Signal: ${bss.signal} dBm Noise: ${bss.noise} dBm\n`);
|
||||
printf(`${padding}Bit Rate: ${bss.bitrate == 'unknown' ? 'unknown' : bss.bitrate + ' MBit/s'}\n`);
|
||||
printf(`${padding}Encryption: ${bss.encryption}\n`);
|
||||
printf(`${padding}Type: nl80211 HW Mode(s): 802.11${bss.hwmode}\n`);
|
||||
printf(`${padding}Hardware: ${bss.hw_type} [${bss.hw_id}]\n`);
|
||||
printf(`${padding}TX power offset: ${bss.power_offset}\n`);
|
||||
printf(`${padding}Channel offset: ${bss.channel_offset}\n`);
|
||||
printf(`${padding}Supports VAPs: ${bss.vaps} PHY name: ${bss.phy}\n`);
|
||||
if (bss.owe_transition_ifname)
|
||||
printf(`${padding}OWE partner: ${bss.owe_transition_ifname}\n`);
|
||||
printf('\n');
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function print_scan(cells) {
|
||||
let idx = 1;
|
||||
|
||||
for (let cell in cells) {
|
||||
printf('Cell %02d - Address: %s\n', idx++, cell.bssid);
|
||||
printf('\t Mode: %s Frequency: %s GHz Band: %s GHz Channel: %d\n', cell.mode, cell.frequency, cell.band, cell.channel);
|
||||
printf('\t Signal: %d dBm Quality: %2d/70\n', cell.dbm, cell.quality);
|
||||
|
||||
if (!length(cell.crypto.key_mgmt))
|
||||
printf('\t Encryption: NONE\n');
|
||||
else
|
||||
printf('\t Encryption: %s (%s)\n', join(' / ', cell.crypto.key_mgmt), join(' / ', cell.crypto.pair));
|
||||
|
||||
if (cell.ht) {
|
||||
printf('\t HT Operation:\n');
|
||||
printf('\t\tPrimary Channel: %d\n', cell.ht.primary_channel);
|
||||
printf('\t\tSecondary Channel Offset: %s\n', cell.ht.secondary_chan_off);
|
||||
printf('\t\tChannel Width: %s\n', cell.ht.chan_width);
|
||||
}
|
||||
|
||||
if (cell.vht) {
|
||||
printf('\t VHT Operation:\n');
|
||||
printf('\t\tCenter Frequency 1: %d\n', cell.vht.center_chan_1);
|
||||
printf('\t\tCenter Frequency 2: %s\n', cell.vht.center_chan_2);
|
||||
printf('\t\tChannel Width: %s\n', cell.vht.chan_width);
|
||||
}
|
||||
|
||||
if (cell.he) {
|
||||
printf('\t HE Operation:\n');
|
||||
printf('\t\tCenter Frequency 1: %d\n', cell.he.center_chan_1);
|
||||
printf('\t\tCenter Frequency 2: %s\n', cell.he.center_chan_2);
|
||||
printf('\t\tChannel Width: %s\n', cell.he.chan_width);
|
||||
}
|
||||
|
||||
if (cell.eht) {
|
||||
printf('\t EHT Operation:\n');
|
||||
printf('\t\tCenter Frequency 1: %d\n', cell.eht.center_chan_1);
|
||||
printf('\t\tCenter Frequency 2: %s\n', cell.eht.center_chan_2);
|
||||
printf('\t\tChannel Width: %s\n', cell.eht.chan_width);
|
||||
}
|
||||
|
||||
printf('\n');
|
||||
}
|
||||
}
|
||||
|
||||
function print_txpowerlist(list) {
|
||||
for (let power in list)
|
||||
printf('%s %2d dbm (%4d mW)\n', power.active ? '*' : ' ', power.dbm, power.mw);
|
||||
}
|
||||
|
||||
let pretty = true;
|
||||
if (ARGV[0] == '-j') {
|
||||
pretty = false;
|
||||
shift(ARGV);
|
||||
}
|
||||
|
||||
if (!length(ARGV)) {
|
||||
let info = iwinfo.info();
|
||||
if (pretty)
|
||||
print_info(info);
|
||||
else
|
||||
printf('%.J\n', info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const commands = {
|
||||
assoclist: [ iwinfo.assoclist, print_assoclist ],
|
||||
countrylist: [ iwinfo.countrylist, print_countrylist ],
|
||||
freqlist: [ iwinfo.freqlist, print_freqlist ],
|
||||
htmodelist: [ iwinfo.htmodelist, print_htmodelist ],
|
||||
info: [ iwinfo.info, print_info ],
|
||||
scan: [ iwinfo.scan, print_scan ],
|
||||
txpowerlist: [ iwinfo.txpowerlist, print_txpowerlist ],
|
||||
};
|
||||
|
||||
if (ARGV[0] == 'nl80211' && ARGV[1] == 'phyname') {
|
||||
let sec_name = ARGV[2];
|
||||
let sec = uci.cursor(null, null, null, { strict: false }).get_all('wireless', sec_name);
|
||||
if (!sec || sec['.type'] != 'wifi-device') {
|
||||
warn(`Config section ${sec_name} not found\n`);
|
||||
return 1;
|
||||
}
|
||||
|
||||
let name = find_phy(sec);
|
||||
if (!name) {
|
||||
warn('Phy not found\n');
|
||||
return 1;
|
||||
}
|
||||
|
||||
print(name + '\n');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (length(ARGV) == 2 && iwinfo.ifaces[ARGV[0]])
|
||||
for (let cmd, cb in commands)
|
||||
if (substr(cmd, 0, length(ARGV[1])) == ARGV[1]) {
|
||||
let ret = cb[0](ARGV[0]);
|
||||
|
||||
if (pretty)
|
||||
cb[1](ret);
|
||||
else
|
||||
printf('%.J\n', ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(ARGV[0]) {
|
||||
case 'phy':
|
||||
printf('%.J\n', iwinfo.phys);
|
||||
return 0;
|
||||
|
||||
case 'iface':
|
||||
printf('%.J\n', iwinfo.ifaces);
|
||||
return 0;
|
||||
}
|
||||
|
||||
warn('Usage:\n' +
|
||||
'\tiwinfo <device> info\n' +
|
||||
'\tiwinfo <device> scan\n' +
|
||||
'\tiwinfo <device> txpowerlist\n' +
|
||||
'\tiwinfo <device> freqlist\n' +
|
||||
'\tiwinfo <device> assoclist\n' +
|
||||
'\tiwinfo <device> countrylist\n' +
|
||||
'\tiwinfo <device> htmodelist\n' +
|
||||
'\tiwinfo nl80211 phyname <section>\n');
|
||||
return 1;
|
||||
@@ -1,249 +0,0 @@
|
||||
{
|
||||
"00": "World",
|
||||
"AD": "Andorra",
|
||||
"AE": "United Arab Emirates",
|
||||
"AF": "Afghanistan",
|
||||
"AG": "Antigua and Barbuda",
|
||||
"AI": "Anguilla",
|
||||
"AL": "Albania",
|
||||
"AM": "Armenia",
|
||||
"AN": "Netherlands Antilles",
|
||||
"AO": "Angola",
|
||||
"AQ": "Antarctica",
|
||||
"AR": "Argentina",
|
||||
"AS": "American Samoa",
|
||||
"AT": "Austria",
|
||||
"AU": "Australia",
|
||||
"AW": "Aruba",
|
||||
"AX": "Aland Islands",
|
||||
"AZ": "Azerbaijan",
|
||||
"BA": "Bosnia and Herzegovina",
|
||||
"BB": "Barbados",
|
||||
"BD": "Bangladesh",
|
||||
"BE": "Belgium",
|
||||
"BF": "Burkina Faso",
|
||||
"BG": "Bulgaria",
|
||||
"BH": "Bahrain",
|
||||
"BI": "Burundi",
|
||||
"BJ": "Benin",
|
||||
"BL": "Saint Barthelemy",
|
||||
"BM": "Bermuda",
|
||||
"BN": "Brunei Darussalam",
|
||||
"BO": "Bolivia",
|
||||
"BR": "Brazil",
|
||||
"BS": "Bahamas",
|
||||
"BT": "Bhutan",
|
||||
"BV": "Bouvet Island",
|
||||
"BW": "Botswana",
|
||||
"BY": "Belarus",
|
||||
"BZ": "Belize",
|
||||
"CA": "Canada",
|
||||
"CC": "Cocos (Keeling) Islands",
|
||||
"CD": "Congo",
|
||||
"CF": "Central African Republic",
|
||||
"CG": "Congo",
|
||||
"CH": "Switzerland",
|
||||
"CI": "Cote d'Ivoire",
|
||||
"CK": "Cook Islands",
|
||||
"CL": "Chile",
|
||||
"CM": "Cameroon",
|
||||
"CN": "China",
|
||||
"CO": "Colombia",
|
||||
"CR": "Costa Rica",
|
||||
"CU": "Cuba",
|
||||
"CV": "Cape Verde",
|
||||
"CX": "Christmas Island",
|
||||
"CY": "Cyprus",
|
||||
"CZ": "Czech Republic",
|
||||
"DE": "Germany",
|
||||
"DJ": "Djibouti",
|
||||
"DK": "Denmark",
|
||||
"DM": "Dominica",
|
||||
"DO": "Dominican Republic",
|
||||
"DZ": "Algeria",
|
||||
"EC": "Ecuador",
|
||||
"EE": "Estonia",
|
||||
"EG": "Egypt",
|
||||
"EH": "Western Sahara",
|
||||
"ER": "Eritrea",
|
||||
"ES": "Spain",
|
||||
"ET": "Ethiopia",
|
||||
"FI": "Finland",
|
||||
"FJ": "Fiji",
|
||||
"FK": "Falkland Islands",
|
||||
"FM": "Micronesia",
|
||||
"FO": "Faroe Islands",
|
||||
"FR": "France",
|
||||
"GA": "Gabon",
|
||||
"GB": "United Kingdom",
|
||||
"GD": "Grenada",
|
||||
"GE": "Georgia",
|
||||
"GF": "French Guiana",
|
||||
"GG": "Guernsey",
|
||||
"GH": "Ghana",
|
||||
"GI": "Gibraltar",
|
||||
"GL": "Greenland",
|
||||
"GM": "Gambia",
|
||||
"GN": "Guinea",
|
||||
"GP": "Guadeloupe",
|
||||
"GQ": "Equatorial Guinea",
|
||||
"GR": "Greece",
|
||||
"GS": "South Georgia",
|
||||
"GT": "Guatemala",
|
||||
"GU": "Guam",
|
||||
"GW": "Guinea-Bissau",
|
||||
"GY": "Guyana",
|
||||
"HK": "Hong Kong",
|
||||
"HM": "Heard and McDonald Islands",
|
||||
"HN": "Honduras",
|
||||
"HR": "Croatia",
|
||||
"HT": "Haiti",
|
||||
"HU": "Hungary",
|
||||
"ID": "Indonesia",
|
||||
"IE": "Ireland",
|
||||
"IL": "Israel",
|
||||
"IM": "Isle of Man",
|
||||
"IN": "India",
|
||||
"IO": "Chagos Islands",
|
||||
"IQ": "Iraq",
|
||||
"IR": "Iran",
|
||||
"IS": "Iceland",
|
||||
"IT": "Italy",
|
||||
"JE": "Jersey",
|
||||
"JM": "Jamaica",
|
||||
"JO": "Jordan",
|
||||
"JP": "Japan",
|
||||
"KE": "Kenya",
|
||||
"KG": "Kyrgyzstan",
|
||||
"KH": "Cambodia",
|
||||
"KI": "Kiribati",
|
||||
"KM": "Comoros",
|
||||
"KN": "Saint Kitts and Nevis",
|
||||
"KP": "North Korea",
|
||||
"KR": "South Korea",
|
||||
"KW": "Kuwait",
|
||||
"KY": "Cayman Islands",
|
||||
"KZ": "Kazakhstan",
|
||||
"LA": "Laos",
|
||||
"LB": "Lebanon",
|
||||
"LC": "Saint Lucia",
|
||||
"LI": "Liechtenstein",
|
||||
"LK": "Sri Lanka",
|
||||
"LR": "Liberia",
|
||||
"LS": "Lesotho",
|
||||
"LT": "Lithuania",
|
||||
"LU": "Luxembourg",
|
||||
"LV": "Latvia",
|
||||
"LY": "Libyan Arab Jamahiriya",
|
||||
"MA": "Morocco",
|
||||
"MC": "Monaco",
|
||||
"MD": "Moldova",
|
||||
"ME": "Montenegro",
|
||||
"MF": "Saint Martin (French part)",
|
||||
"MG": "Madagascar",
|
||||
"MH": "Marshall Islands",
|
||||
"MK": "Macedonia",
|
||||
"ML": "Mali",
|
||||
"MM": "Myanmar",
|
||||
"MN": "Mongolia",
|
||||
"MO": "Macao",
|
||||
"MP": "Northern Mariana Islands",
|
||||
"MQ": "Martinique",
|
||||
"MR": "Mauritania",
|
||||
"MS": "Montserrat",
|
||||
"MT": "Malta",
|
||||
"MU": "Mauritius",
|
||||
"MV": "Maldives",
|
||||
"MW": "Malawi",
|
||||
"MX": "Mexico",
|
||||
"MY": "Malaysia",
|
||||
"MZ": "Mozambique",
|
||||
"NA": "Namibia",
|
||||
"NC": "New Caledonia",
|
||||
"NE": "Niger",
|
||||
"NF": "Norfolk Island",
|
||||
"NG": "Nigeria",
|
||||
"NI": "Nicaragua",
|
||||
"NL": "Netherlands",
|
||||
"NO": "Norway",
|
||||
"NP": "Nepal",
|
||||
"NR": "Nauru",
|
||||
"NU": "Niue",
|
||||
"NZ": "New Zealand",
|
||||
"OM": "Oman",
|
||||
"PA": "Panama",
|
||||
"PE": "Peru",
|
||||
"PF": "French Polynesia",
|
||||
"PG": "Papua New Guinea",
|
||||
"PH": "Philippines",
|
||||
"PK": "Pakistan",
|
||||
"PL": "Poland",
|
||||
"PM": "Saint Pierre and Miquelon",
|
||||
"PN": "Pitcairn",
|
||||
"PR": "Puerto Rico",
|
||||
"PS": "Palestinian Territory",
|
||||
"PT": "Portugal",
|
||||
"PW": "Palau",
|
||||
"PY": "Paraguay",
|
||||
"QA": "Qatar",
|
||||
"RE": "Reunion",
|
||||
"RO": "Romania",
|
||||
"RS": "Serbia",
|
||||
"RU": "Russian Federation",
|
||||
"RW": "Rwanda",
|
||||
"SA": "Saudi Arabia",
|
||||
"SB": "Solomon Islands",
|
||||
"SC": "Seychelles",
|
||||
"SD": "Sudan",
|
||||
"SE": "Sweden",
|
||||
"SG": "Singapore",
|
||||
"SH": "St. Helena and Dependencies",
|
||||
"SI": "Slovenia",
|
||||
"SJ": "Svalbard and Jan Mayen",
|
||||
"SK": "Slovakia",
|
||||
"SL": "Sierra Leone",
|
||||
"SM": "San Marino",
|
||||
"SN": "Senegal",
|
||||
"SO": "Somalia",
|
||||
"SR": "Suriname",
|
||||
"ST": "Sao Tome and Principe",
|
||||
"SV": "El Salvador",
|
||||
"SY": "Syrian Arab Republic",
|
||||
"SZ": "Swaziland",
|
||||
"TC": "Turks and Caicos Islands",
|
||||
"TD": "Chad",
|
||||
"TF": "French Southern Territories",
|
||||
"TG": "Togo",
|
||||
"TH": "Thailand",
|
||||
"TJ": "Tajikistan",
|
||||
"TK": "Tokelau",
|
||||
"TL": "Timor-Leste",
|
||||
"TM": "Turkmenistan",
|
||||
"TN": "Tunisia",
|
||||
"TO": "Tonga",
|
||||
"TR": "Turkey",
|
||||
"TT": "Trinidad and Tobago",
|
||||
"TV": "Tuvalu",
|
||||
"TW": "Taiwan",
|
||||
"TZ": "Tanzania",
|
||||
"UA": "Ukraine",
|
||||
"UG": "Uganda",
|
||||
"UM": "U.S. Minor Outlying Islands",
|
||||
"US": "United States",
|
||||
"UY": "Uruguay",
|
||||
"UZ": "Uzbekistan",
|
||||
"VA": "Vatican City State",
|
||||
"VC": "St. Vincent and Grenadines",
|
||||
"VE": "Venezuela",
|
||||
"VG": "Virgin Islands, British",
|
||||
"VI": "Virgin Islands, U.S.",
|
||||
"VN": "Viet Nam",
|
||||
"VU": "Vanuatu",
|
||||
"WF": "Wallis and Futuna",
|
||||
"WS": "Samoa",
|
||||
"YE": "Yemen",
|
||||
"YT": "Mayotte",
|
||||
"ZA": "South Africa",
|
||||
"ZM": "Zambia",
|
||||
"ZW": "Zimbabwe"
|
||||
}
|
||||
@@ -1,742 +0,0 @@
|
||||
{
|
||||
"$id": "https://openwrt.org/wifi.device.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"description": "OpenWrt WiFi Device Schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"acs_chan_bias": {
|
||||
"description": "Can be used to increase (or decrease) the likelihood of a specific channel to be selected by the ACS algorithm",
|
||||
"type": "string"
|
||||
},
|
||||
"acs_exclude_dfs": {
|
||||
"description": "Exclude DFS channels from ACS",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"airtime_mode": {
|
||||
"description": "Set the airtime policy operating mode",
|
||||
"type": "number",
|
||||
"default": 0,
|
||||
"minimum": 0,
|
||||
"maximum": 3
|
||||
},
|
||||
"antenna_gain": {
|
||||
"description": "Reduction in antenna gain from regulatory maximum in dBi",
|
||||
"type": "number",
|
||||
"default": 0
|
||||
},
|
||||
"assoc_sa_query_max_timeout": {
|
||||
"description": "Association SA Query maximum timeout",
|
||||
"type": "number"
|
||||
},
|
||||
"assoc_sa_query_retry_timeout": {
|
||||
"description": "Association SA Query retry timeout",
|
||||
"type": "number"
|
||||
},
|
||||
"auth_cache": {
|
||||
"type": "alias",
|
||||
"default": "okc"
|
||||
},
|
||||
"background_radar": {
|
||||
"type": "alias",
|
||||
"default": "enable_background_radar"
|
||||
},
|
||||
"band": {
|
||||
"description": "The wireless band thatthe radio shall operate on",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"2g",
|
||||
"5g",
|
||||
"6g",
|
||||
"60g"
|
||||
]
|
||||
},
|
||||
"basic_rate": {
|
||||
"type": "alias",
|
||||
"default": "basic_rates"
|
||||
},
|
||||
"basic_rates": {
|
||||
"description": "Set the supported basic rates. Each basic_rate is measured in kb/s. This option only has an effect on ap and adhoc wifi-ifaces. ",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"beacon_int": {
|
||||
"description": "Set the beacon interval. This is the time interval between beacon frames, measured in units of 1.024 ms. hostapd permits this to be set between 15 and 65535. This option only has an effect on ap and adhoc wifi-ifaces",
|
||||
"type": "number",
|
||||
"default": 100,
|
||||
"minimum": 15,
|
||||
"maximum": 65535
|
||||
},
|
||||
"beacon_rate": {
|
||||
"description": "Beacon frame TX rate configuration",
|
||||
"type": "string"
|
||||
},
|
||||
"beamformee_antennas": {
|
||||
"description": "Beamformee antenna override",
|
||||
"type": "number",
|
||||
"default": 4
|
||||
},
|
||||
"beamformer_antennas": {
|
||||
"description": "Beamformer antenna override",
|
||||
"type": "number",
|
||||
"default": 4
|
||||
},
|
||||
"bssid": {
|
||||
"description": "Overrides the MAC address used for the Wi-Fi interface. Warning: if the MAC address specified is a multicast address, this override will fail silently. To avoid this problem, ensure that the mac address specified is a valid unicast mac address",
|
||||
"type": "string"
|
||||
},
|
||||
"cell_density": {
|
||||
"description": "Configures data rates based on the coverage cell density. Normal configures basic rates to 6, 12, 24 Mbps if legacy_rates is 0, else to 5.5, 11 Mbps. High configures basic rates to 12, 24 Mbps if legacy_rates is 0, else to the 11 Mbps rate. Very High configures 24 Mbps as the basic rate. Supported rates lower than the minimum basic rate are not offered. The basic_rate and supported_rates options overrides this option. 0 = Disabled, 1 = Normal, 2 = High, 3 = Very High",
|
||||
"type": "number",
|
||||
"default": 0,
|
||||
"minimum": 0,
|
||||
"maximum": 3
|
||||
},
|
||||
"chanbw": {
|
||||
"description": "Specifies a narrow channel width in MHz, possible values are: 5, 10, 20",
|
||||
"type": "number",
|
||||
"enum": [ 5, 10, 20 ]
|
||||
},
|
||||
"channel": {
|
||||
"description": "Specifies the wireless channel. “auto” defaults to the lowest available channel, or utilizes the ACS algorithm depending on hardware/driver support",
|
||||
"type": "string"
|
||||
},
|
||||
"channels": {
|
||||
"type": "alias",
|
||||
"default": "chanlist"
|
||||
},
|
||||
"channel_list": {
|
||||
"type": "alias",
|
||||
"default": "chanlist"
|
||||
},
|
||||
"chanlist": {
|
||||
"description": "Use specific channels, when channel is in “auto” mode. This option allows hostapd to select one of the provided channels when a channel should be automatically selected. Channels can be provided as range using hyphen ('-') or individual channels can be specified by space (' ') separated values",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"country": {
|
||||
"type": "alias",
|
||||
"default": "country_code"
|
||||
},
|
||||
"country3": {
|
||||
"description": "The third octet of the Country String (dot11CountryString)",
|
||||
"type": "string"
|
||||
},
|
||||
"country_code": {
|
||||
"description": "Specifies the two-letter country code (e.g. EN or DE), affects the available channels and transmission powers",
|
||||
"type": "string"
|
||||
},
|
||||
"country_ie": {
|
||||
"type": "alias",
|
||||
"default": "ieee80211d"
|
||||
},
|
||||
"disabled": {
|
||||
"description": "When set to 1, wireless network is disabled",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"distance": {
|
||||
"description": "Distance between the ap and the furthest client in meters",
|
||||
"type": "number",
|
||||
"default": 0
|
||||
},
|
||||
"doth": {
|
||||
"type": "alias",
|
||||
"default": "ieee80211h"
|
||||
},
|
||||
"dsss_cck_40": {
|
||||
"description": "DSSS/CCK Mode in 40 MHz allowed in Beacon, Measurement Pilot and Probe Response frames",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"enable_background_radar": {
|
||||
"description": "This feature allows CAC to be run on dedicated radio RF chains",
|
||||
"type": "boolean"
|
||||
},
|
||||
"frag": {
|
||||
"description": "Fragmentation threshold",
|
||||
"type": "number"
|
||||
},
|
||||
"greenfield": {
|
||||
"description": "Receive Greenfield - treats pre-80211n traffic as noise",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"he_bss_color": {
|
||||
"description": "BSS color to be announced",
|
||||
"type": "number",
|
||||
"minimum": 1,
|
||||
"maximum": 128,
|
||||
"default": 128
|
||||
},
|
||||
"he_bss_color_enabled": {
|
||||
"description": "Enable BSS color",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"he_default_pe_duration": {
|
||||
"description": "The duration of PE field in an HE PPDU in us",
|
||||
"type": "number",
|
||||
"default": 4,
|
||||
"enum": [ 4, 8, 12, 16 ]
|
||||
},
|
||||
"he_mu_beamformer": {
|
||||
"description": "HE multiple user beamformer support",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"he_mu_edca_ac_be_aci": {
|
||||
"type": "number",
|
||||
"default": 0
|
||||
},
|
||||
"he_mu_edca_ac_be_aifsn": {
|
||||
"type": "number",
|
||||
"default": 8
|
||||
},
|
||||
"he_mu_edca_ac_be_ecwmax": {
|
||||
"type": "number",
|
||||
"default": 10
|
||||
},
|
||||
"he_mu_edca_ac_be_ecwmin": {
|
||||
"type": "number",
|
||||
"default": 9
|
||||
},
|
||||
"he_mu_edca_ac_be_timer": {
|
||||
"type": "number",
|
||||
"default": 255
|
||||
},
|
||||
"he_mu_edca_ac_bk_aci": {
|
||||
"type": "number",
|
||||
"default": 1
|
||||
},
|
||||
"he_mu_edca_ac_bk_aifsn": {
|
||||
"type": "number",
|
||||
"default": 15
|
||||
},
|
||||
"he_mu_edca_ac_bk_ecwmax": {
|
||||
"type": "number",
|
||||
"default": 10
|
||||
},
|
||||
"he_mu_edca_ac_bk_ecwmin": {
|
||||
"type": "number",
|
||||
"default": 9
|
||||
},
|
||||
"he_mu_edca_ac_bk_timer": {
|
||||
"type": "number",
|
||||
"default": 255
|
||||
},
|
||||
"he_mu_edca_ac_vi_aci": {
|
||||
"type": "number",
|
||||
"default": 2
|
||||
},
|
||||
"he_mu_edca_ac_vi_aifsn": {
|
||||
"type": "number",
|
||||
"default": 5
|
||||
},
|
||||
"he_mu_edca_ac_vi_ecwmax": {
|
||||
"type": "number",
|
||||
"default": 7
|
||||
},
|
||||
"he_mu_edca_ac_vi_ecwmin": {
|
||||
"type": "number",
|
||||
"default": 5
|
||||
},
|
||||
"he_mu_edca_ac_vi_timer": {
|
||||
"type": "number",
|
||||
"default": 255
|
||||
},
|
||||
"he_mu_edca_ac_vo_aci": {
|
||||
"type": "number",
|
||||
"default": 3
|
||||
},
|
||||
"he_mu_edca_ac_vo_aifsn": {
|
||||
"type": "number",
|
||||
"default": 5
|
||||
},
|
||||
"he_mu_edca_ac_vo_ecwmax": {
|
||||
"type": "number",
|
||||
"default": 7
|
||||
},
|
||||
"he_mu_edca_ac_vo_ecwmin": {
|
||||
"type": "number",
|
||||
"default": 5
|
||||
},
|
||||
"he_mu_edca_ac_vo_timer": {
|
||||
"type": "number",
|
||||
"default": 255
|
||||
},
|
||||
"he_mu_edca_qos_info_param_count": {
|
||||
"type": "number",
|
||||
"default": 0
|
||||
},
|
||||
"he_mu_edca_qos_info_q_ack": {
|
||||
"type": "number",
|
||||
"default": 0
|
||||
},
|
||||
"he_mu_edca_qos_info_queue_request": {
|
||||
"type": "number",
|
||||
"default": 0
|
||||
},
|
||||
"he_mu_edca_qos_info_txop_request": {
|
||||
"type": "number",
|
||||
"default": 0
|
||||
},
|
||||
"he_oper_centr_freq_seg0_idx": {
|
||||
"description": "",
|
||||
"type": "string"
|
||||
},
|
||||
"he_oper_chwidth": {
|
||||
"description": "",
|
||||
"type": "string"
|
||||
},
|
||||
"he_6ghz_reg_pwr_type": {
|
||||
"description": "This config is to set the 6 GHz Access Point type.",
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 4,
|
||||
"default": 0
|
||||
},
|
||||
"he_rts_threshold": {
|
||||
"description": "Duration of STA transmission",
|
||||
"type": "number",
|
||||
"default": 1023
|
||||
},
|
||||
"he_spr_non_srg_obss_pd_max_offset": {
|
||||
"description": "",
|
||||
"type": "number"
|
||||
},
|
||||
"he_spr_psr_enabled": {
|
||||
"description": "",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"he_spr_sr_control": {
|
||||
"description": "",
|
||||
"type": "number",
|
||||
"default": 3
|
||||
},
|
||||
"he_su_beamformee": {
|
||||
"description": "",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"he_su_beamformer": {
|
||||
"description": "",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"he_twt_required": {
|
||||
"description": "",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"hostapd_options": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"ht_coex": {
|
||||
"description": "Disable honoring 40 MHz intolerance in coexistence flags of stations",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"htc_vht": {
|
||||
"description": "STA supports receiving a VHT variant HT Control field",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"htmode": {
|
||||
"description": "Specifies the high throughput mode",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"NOHT", "HT20", "HT40-", "HT40+", "HT40",
|
||||
"VHT20", "VHT40", "VHT80", "VHT160",
|
||||
"HE20", "HE40", "HE80", "HE160",
|
||||
"EHT20", "EHT40", "EHT80", "EHT160", "EHT320" ]
|
||||
},
|
||||
"hwmode": {
|
||||
"type": "alias",
|
||||
"default": "hw_mode"
|
||||
},
|
||||
"hw_mode": {
|
||||
"description": "Legacy way, use the band property instead",
|
||||
"type": "string",
|
||||
"enum": [ "11a", "11b", "11g", "11ad" ]
|
||||
},
|
||||
"ieee80211d": {
|
||||
"description": "Enables IEEE 802.11d country IE (information element) advertisement in beacon and probe response frames. This IE contains the country code and channel/power map. Requires country",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"ieee80211h": {
|
||||
"description": "This enables radar detection and DFS support",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"ieee80211w": {
|
||||
"description": "Whether management frame protection (MFP) is enabled",
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 2
|
||||
},
|
||||
"ieee80211w_max_timeout": {
|
||||
"type": "alias",
|
||||
"default": "assoc_sa_query_max_timeout"
|
||||
},
|
||||
"ieee80211w_mgmt_cipher": {
|
||||
"description": "Cypher used for MFP",
|
||||
"type": "string"
|
||||
},
|
||||
"ieee80211w_retry_timeout": {
|
||||
"type": "alias",
|
||||
"default": "assoc_sa_query_retry_timeout"
|
||||
},
|
||||
"ifname_prefix": {
|
||||
"description": "Default ifname prefix for this radio",
|
||||
"type": "string"
|
||||
},
|
||||
"iface_max_num_sta": {
|
||||
"description": "Limits the maximum allowed number of associated clients",
|
||||
"type": "number"
|
||||
},
|
||||
"ldpc": {
|
||||
"description": " LDPC (Low-Density Parity-Check code) capability ",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"legacy_rates": {
|
||||
"description": "Allow legacy 802.11b data rates (used by cell_density)",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"local_pwr_constraint": {
|
||||
"description": "Add Power Constraint element to Beacon and Probe Response frame",
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 255
|
||||
},
|
||||
"log_80211": {
|
||||
"description": "Enable IEEE 802.11 logging",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"log_8021x": {
|
||||
"description": "Enable IEEE 802.1X logging",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"log_driver": {
|
||||
"description": "Enable driver interface logging",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"log_iapp": {
|
||||
"description": "Enable iapp logging",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"log_level": {
|
||||
"description": "Log severity",
|
||||
"type": "number",
|
||||
"default": 2,
|
||||
"minimum": 0,
|
||||
"maximum": 4
|
||||
},
|
||||
"log_mlme": {
|
||||
"description": "Enable MLME logging",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"log_radius": {
|
||||
"description": "Enable Radius logging",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"log_wpa": {
|
||||
"description": "Enable WPA logging",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"logger_stdout": {
|
||||
"description": "Log to stdout",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"logger_stdout_level": {
|
||||
"description": "Log severity",
|
||||
"type": "number",
|
||||
"default": 2,
|
||||
"minimum": 0,
|
||||
"maximum": 4
|
||||
},
|
||||
"logger_syslog": {
|
||||
"description": "Log to syslog",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"logger_syslog_level": {
|
||||
"description": "Syslog severity",
|
||||
"type": "number",
|
||||
"default": 2,
|
||||
"minimum": 0,
|
||||
"maximum": 4
|
||||
},
|
||||
"macaddr": {
|
||||
"type": "alias",
|
||||
"default": "bssid"
|
||||
},
|
||||
"macaddr_base": {
|
||||
"type": "string",
|
||||
"description": "Base MAC address used for deriving interface MAC addresses"
|
||||
},
|
||||
"max_amsdu": {
|
||||
"description": "Maximum A-MSDU length of 7935 octects (3839 octets if option set to 0)",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"maxassoc": {
|
||||
"type": "alias",
|
||||
"default": "iface_max_num_sta"
|
||||
},
|
||||
"mbssid": {
|
||||
"description": "Multiple BSSID Advertisement in IEEE 802.11ax IEEE Std 802.11ax-2021 added a feature where instead of multiple interfaces on a common radio transmitting individual Beacon frames, those interfaces can form a set with a common Beacon frame transmitted for all Set minimum permitted max TX power (in dBm) for ACS and DFS channel selection",
|
||||
"type": "number",
|
||||
"default": 0,
|
||||
"minimum": 0,
|
||||
"maximum": 2
|
||||
},
|
||||
"min_tx_power": {
|
||||
"description": "Set minimum permitted max TX power (in dBm) for ACS and DFS channel selection",
|
||||
"type": "number",
|
||||
"default": 0
|
||||
},
|
||||
"mu_beamformee": {
|
||||
"description": "Supports operation as an MU beamformee",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"mu_beamformer": {
|
||||
"description": " Supports operation as an MU beamformer",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"multiple_bssid": {
|
||||
"type": "alias",
|
||||
"default": "mbssid"
|
||||
},
|
||||
"num_global_macaddr": {
|
||||
"description": "The number of MACs that this radio can use",
|
||||
"type": "number",
|
||||
"default": 1
|
||||
},
|
||||
"no_probe_resp_if_max_sta": {
|
||||
"description": "Do not answer probe requests if iface_max_num_sta was reached",
|
||||
"type": "boolean"
|
||||
},
|
||||
"noscan": {
|
||||
"description": "Do not scan for overlapping BSSs in HT40+/- mode.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"okc": {
|
||||
"description": "Enable Opportunistic Key Caching",
|
||||
"type": "boolean"
|
||||
},
|
||||
"path": {
|
||||
"description": "Alternative to phy used to identify the device based paths in /sys/devices",
|
||||
"type": "string"
|
||||
},
|
||||
"phy": {
|
||||
"description": "Name of the phy, as described in board.json",
|
||||
"type": "string"
|
||||
},
|
||||
"radio": {
|
||||
"description": "Index of the phy radio (for multi-radio PHYs)",
|
||||
"type": "number",
|
||||
"default": -1
|
||||
},
|
||||
"reg_power_type": {
|
||||
"type": "alias",
|
||||
"default": "he_6ghz_reg_pwr_type"
|
||||
},
|
||||
"require_mode": {
|
||||
"description": "Sets the minimum client capability level mode that connecting clients must support to be allowed to connect",
|
||||
"type": "string",
|
||||
"enum": [ "n", "ac", "ax" ]
|
||||
},
|
||||
"rnr_beacon": {
|
||||
"description": "",
|
||||
"type": "string"
|
||||
},
|
||||
"rsn_preauth": {
|
||||
"description": "Enable IEEE 802.11i/RSN/WPA2 pre-authentication",
|
||||
"type": "boolean"
|
||||
},
|
||||
"rssi_ignore_probe_request": {
|
||||
"description": "Ignore Probe Request frames if RSSI is below given threshold (in dBm)",
|
||||
"type": "number",
|
||||
"default": 0
|
||||
},
|
||||
"rssi_reject_assoc_rssi": {
|
||||
"description": "Reject STA association if RSSI is below given threshold (in dBm)",
|
||||
"type": "number",
|
||||
"default": 0
|
||||
},
|
||||
"rts": {
|
||||
"description": "Override the RTS/CTS threshold",
|
||||
"type": "number"
|
||||
},
|
||||
"rts_threshold": {
|
||||
"description": "RTS/CTS threshold",
|
||||
"type": "number",
|
||||
"minimum": -1,
|
||||
"maximum": 65535
|
||||
},
|
||||
"rx_antenna_pattern": {
|
||||
"description": "Rx antenna pattern does not change during the lifetime of an association",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"rx_stbc": {
|
||||
"description": "Supports reception of PPDUs using STBC",
|
||||
"type": "number",
|
||||
"default": 3,
|
||||
"minimum": 0,
|
||||
"maximum": 4
|
||||
},
|
||||
"rxantenna": {
|
||||
"description": "Specifies the antenna for receiving, the value may be driver specific, usually it is 1 for the first and 2 for the second antenna. Specifying 0 enables automatic selection by the driver if supported. This option has no effect if diversity is enabled",
|
||||
"type": "number"
|
||||
},
|
||||
"rxldpc": {
|
||||
"description": "Supports receiving LDPC coded pkts",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"scan_list": {
|
||||
"description": "List of frequencies (in MHz) to scan when looking for networks in client mode",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"short_gi_160": {
|
||||
"description": "Short GI for 160 MHz",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"short_gi_20": {
|
||||
"description": "Short GI for 20 MHz",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"short_gi_40": {
|
||||
"description": "Short GI for 40 MHz",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"short_gi_80": {
|
||||
"description": "Short GI for 80 MHz",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"spectrum_mgmt_required": {
|
||||
"description": "Set Spectrum Management subfield in the Capability Information field",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"stationary_ap": {
|
||||
"description": "Stationary AP config indicates that the AP doesn't move hence location data can be considered as always up to date.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"su_beamformee": {
|
||||
"description": "Single user beamformee",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"su_beamformer": {
|
||||
"description": "Single user beamformer",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"supported_rates": {
|
||||
"description": "Set the supported data rates. Each supported rate is measured in kb/s. This option only has an effect on ap and adhoc wifi-ifaces. This must be a superset of the rates set in basic_rate. The minimum basic rate should also be the minimum supported rate. It is recommended to use the cell_density option instead",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"tx_antenna_pattern": {
|
||||
"description": "Tx antenna pattern does not change during the lifetime of an association",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"tx_burst": {
|
||||
"type": "alias",
|
||||
"default": "tx_queue_data2_burst"
|
||||
},
|
||||
"tx_queue_data2_burst": {
|
||||
"description": "",
|
||||
"type": "number"
|
||||
},
|
||||
"tx_stbc": {
|
||||
"description": "Transmit STBC (Space-Time Block Coding)",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"tx_stbc_2by1": {
|
||||
"description": "Supports transmission of at least 2×1 STBC",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"txantenna": {
|
||||
"description": "Specifies the antenna for transmitting, values are identical to rxantenna",
|
||||
"type": "number"
|
||||
},
|
||||
"txpower": {
|
||||
"description": "Specifies the maximum desired transmission power in dBm. The actual txpower used depends on regulatory requirements",
|
||||
"type": "number"
|
||||
},
|
||||
"type": {
|
||||
"description": "Device type (only mac80211 supported)",
|
||||
"type": "string"
|
||||
},
|
||||
"vht160": {
|
||||
"description": "Supported channel widths. 0 == 160MHz and 80+80 MHz not supported, 1 == 160 MHz supported, 2 == 160MHz and 80+80 MHz supported",
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 2,
|
||||
"default": 2
|
||||
},
|
||||
"vht_link_adapt": {
|
||||
"description": "TA supports link adaptation using VHT variant HT Control field",
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 3
|
||||
},
|
||||
"vht_max_a_mpdu_len_exp": {
|
||||
"description": "Indicates the maximum length of A-MPDU pre-EOF padding that the STA can recv",
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 7,
|
||||
"default": 7
|
||||
},
|
||||
"vht_max_mpdu": {
|
||||
"description": "Maximum MPDU length",
|
||||
"type": "number",
|
||||
"enum": [ 3895, 7991, 11454 ],
|
||||
"default": 11454
|
||||
},
|
||||
"vht_txop_ps": {
|
||||
"description": "VHT TXOP PS mode",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"$id": "https://openwrt.org/wifi.station.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"description": "OpenWrt WiFi Station Schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mac": {
|
||||
"description": "The stations MAC",
|
||||
"type": "string",
|
||||
"default": "00:00:00:00:00:00"
|
||||
},
|
||||
"key": {
|
||||
"description": "The passphrase that shall be used",
|
||||
"type": "string"
|
||||
},
|
||||
"vid": {
|
||||
"description": "The VLAN Id used by the station",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"$id": "https://openwrt.org/wifi.vlan.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"description": "OpenWrt WiFi VLAN Schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "VLAN name",
|
||||
"type": "string"
|
||||
},
|
||||
"vid": {
|
||||
"description": "VLAN ID",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,642 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import * as nl80211 from 'nl80211';
|
||||
import * as libubus from 'ubus';
|
||||
import { readfile, stat } from "fs";
|
||||
|
||||
let wifi_devices = json(readfile('/usr/share/wifi_devices.json'));
|
||||
let countries = json(readfile('/usr/share/iso3166.json'));
|
||||
let board_data = json(readfile('/etc/board.json'));
|
||||
|
||||
export let phys = nl80211.request(nl80211.const.NL80211_CMD_GET_WIPHY, nl80211.const.NLM_F_DUMP, { split_wiphy_dump: true });
|
||||
let interfaces = nl80211.request(nl80211.const.NL80211_CMD_GET_INTERFACE, nl80211.const.NLM_F_DUMP);
|
||||
|
||||
let ubus = libubus.connect();
|
||||
let wireless_status = ubus.call('network.wireless', 'status');
|
||||
|
||||
function find_phy(wiphy) {
|
||||
for (let k, phy in phys)
|
||||
if (phy && phy.wiphy == wiphy)
|
||||
return phy;
|
||||
return null;
|
||||
}
|
||||
|
||||
function get_noise(iface) {
|
||||
for (let phy in phys) {
|
||||
let channels = nl80211.request(nl80211.const.NL80211_CMD_GET_SURVEY, nl80211.const.NLM_F_DUMP, { dev: iface.ifname });
|
||||
for (let k, channel in channels)
|
||||
if (channel.survey_info.frequency == iface.wiphy_freq)
|
||||
return channel.survey_info.noise;
|
||||
}
|
||||
|
||||
return -100;
|
||||
}
|
||||
|
||||
function get_country(iface) {
|
||||
let reg = nl80211.request(nl80211.const.NL80211_CMD_GET_REG, 0, { dev: iface.ifname });
|
||||
|
||||
return reg.reg_alpha2 ?? '';
|
||||
}
|
||||
|
||||
function get_max_power(iface) {
|
||||
let phy = find_phy(iface.wiphy);
|
||||
|
||||
for (let k, band in phy.wiphy_bands)
|
||||
if (band)
|
||||
for (let freq in band.freqs)
|
||||
if (freq.freq == iface.wiphy_freq)
|
||||
return freq.max_tx_power;;
|
||||
return 0;
|
||||
}
|
||||
|
||||
function get_hardware_id(iface) {
|
||||
let hw = {
|
||||
type: 'nl80211',
|
||||
id: 'Generic MAC80211',
|
||||
power_offset: 0,
|
||||
channel_offset: 0,
|
||||
};
|
||||
|
||||
let path = `/sys/class/ieee80211/phy${iface.wiphy}/device/`;
|
||||
if (stat(path + 'vendor')) {
|
||||
let data = [];
|
||||
for (let lookup in [ 'vendor', 'device', 'subsystem_vendor', 'subsystem_device' ])
|
||||
push(data, trim(readfile(path + lookup), '\n'));
|
||||
|
||||
for (let device in wifi_devices.pci) {
|
||||
let match = 0;
|
||||
for (let i = 0; i < 4; i++)
|
||||
if (lc(data[i]) == lc(device[i]))
|
||||
match++;
|
||||
if (match == 4) {
|
||||
hw.type = `${data[0]}:${data[1]} ${data[2]}:${data[3]}`;
|
||||
hw.power_offset = device[4];
|
||||
hw.channel_offset = device[5];
|
||||
hw.id = `${device[6]} ${device[7]}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let compatible = trim(readfile(`/sys/class/net/${iface.ifname}/device/of_node/compatible`), '\n');
|
||||
if (compatible && wifi_devices.compatible[compatible]) {
|
||||
hw.id = wifi_devices.compatible[compatible][0] + ' ' + wifi_devices.compatible[compatible][1];
|
||||
hw.compatible = compatible;
|
||||
hw.type = 'embedded';
|
||||
}
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
const iftypes = [
|
||||
'Unknown', 'Ad-Hoc', 'Client', 'Master', 'Master (VLAN)',
|
||||
'WDS', 'Monitor', 'Mesh Point', 'P2P Client', 'P2P Go',
|
||||
];
|
||||
|
||||
export let ifaces = {};
|
||||
for (let k, v in interfaces) {
|
||||
let iface = ifaces[v.ifname] = v;
|
||||
|
||||
iface.mode = iftypes[iface.iftype] ?? 'unknown',
|
||||
iface.noise = get_noise(iface);
|
||||
iface.country = get_country(iface);
|
||||
iface.max_power = get_max_power(iface);
|
||||
iface.assoclist = nl80211.request(nl80211.const.NL80211_CMD_GET_STATION, nl80211.const.NLM_F_DUMP, { dev: v.ifname }) ?? [];
|
||||
iface.hardware = get_hardware_id(iface);
|
||||
|
||||
iface.bss_info = ubus.call('hostapd', 'bss_info', { iface: v.ifname });
|
||||
if (!iface.bss_info)
|
||||
iface.bss_info = ubus.call('wpa_supplicant', 'bss_info', { iface: v.ifname });
|
||||
}
|
||||
|
||||
for (let radio, data in wireless_status)
|
||||
for (let k, v in data.interfaces) {
|
||||
if (!v.ifname || !ifaces[v.ifname])
|
||||
continue;
|
||||
|
||||
ifaces[v.ifname].ssid = v.config.ssid || v.config.mesh_id;
|
||||
ifaces[v.ifname].radio = data.config;
|
||||
|
||||
let bss_info = ifaces[v.ifname].bss_info;
|
||||
let owe_transition_ifname = bss_info?.owe_transition_ifname;
|
||||
|
||||
if (v.config.owe_transition && ifaces[owe_transition_ifname]) {
|
||||
ifaces[v.ifname].owe_transition_ifname = owe_transition_ifname;
|
||||
ifaces[owe_transition_ifname].ssid = v.config.ssid;
|
||||
ifaces[owe_transition_ifname].radio = data.config;
|
||||
ifaces[owe_transition_ifname].owe_transition_ifname = v.ifname
|
||||
}
|
||||
}
|
||||
|
||||
function format_channel(freq) {
|
||||
if (freq < 1000)
|
||||
return 0;
|
||||
if (freq == 2484)
|
||||
return 14;
|
||||
if (freq == 5935)
|
||||
return 2;
|
||||
if (freq < 2484)
|
||||
return (freq - 2407) / 5;
|
||||
if (freq >= 4910 && freq <= 4980)
|
||||
return (freq - 4000) / 5;
|
||||
if (freq < 5950)
|
||||
return (freq - 5000) / 5;
|
||||
if (freq <= 45000)
|
||||
return (freq - 5950) / 5;
|
||||
if (freq >= 58320 && freq <= 70200)
|
||||
return (freq - 56160) / 2160;
|
||||
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
function format_band(freq) {
|
||||
if (freq == 5935)
|
||||
return '6';
|
||||
if (freq < 2484)
|
||||
return '2.4';
|
||||
if (freq < 5950)
|
||||
return '5';
|
||||
if (freq <= 45000)
|
||||
return '6';
|
||||
|
||||
return '60';
|
||||
}
|
||||
|
||||
function format_frequency(freq) {
|
||||
return freq ? sprintf('%.03f', freq / 1000.0) : 'unknown';
|
||||
}
|
||||
|
||||
function format_rate(rate) {
|
||||
return rate ? sprintf('%.01f', rate / 10.0) : 'unknown';
|
||||
}
|
||||
|
||||
function format_mgmt_key(key) {
|
||||
switch(+key) {
|
||||
case 1:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 16:
|
||||
case 17:
|
||||
return '802.1x';
|
||||
|
||||
case 2:
|
||||
return 'WPA PSK';
|
||||
|
||||
case 4:
|
||||
return 'FT PSK';
|
||||
|
||||
case 6:
|
||||
return 'WPA PSK2';
|
||||
|
||||
case 8:
|
||||
return 'SAE';
|
||||
|
||||
case 18:
|
||||
return 'OWE';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function assoc_flags(data) {
|
||||
const assoc_mhz = {
|
||||
width_40: 40,
|
||||
width_80: 80,
|
||||
width_80p80: '80+80',
|
||||
width_160: 160,
|
||||
width_320: 320,
|
||||
width_10: 10,
|
||||
width_5: 5
|
||||
};
|
||||
|
||||
let mhz = 'unknown';
|
||||
for (let k, v in assoc_mhz)
|
||||
if (data[k])
|
||||
mhz = v;
|
||||
|
||||
const assoc_flags = {
|
||||
mcs: {
|
||||
mcs: 'MCS',
|
||||
},
|
||||
vht_mcs: {
|
||||
vht_mcs: 'VHT-MCS',
|
||||
vht_nss: 'VHT-NSS',
|
||||
},
|
||||
he_mcs: {
|
||||
he_mcs: 'HE-MCS',
|
||||
he_nss: 'HE-NSS',
|
||||
he_gi: 'HE-GI',
|
||||
he_dcm: 'HE-DCM',
|
||||
},
|
||||
eht_mcs: {
|
||||
eht_mcs: 'EHT-MCS',
|
||||
eht_nss: 'EHT-NSS',
|
||||
eht_gi: 'EHT-GI',
|
||||
},
|
||||
};
|
||||
|
||||
let flags = [];
|
||||
for (let k, v in assoc_flags) {
|
||||
if (!data[k])
|
||||
continue;
|
||||
|
||||
let first = 0;
|
||||
for (let name, flag in v) {
|
||||
if (data[name] == null)
|
||||
continue;
|
||||
push(flags, `${flag} ${data[name]}`);
|
||||
if (!first++)
|
||||
push(flags, `${mhz}MHz`);
|
||||
}
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
function dbm2mw(dbm) {
|
||||
const LOG10_MAGIC = 1.25892541179;
|
||||
let res = 1.0;
|
||||
let ip = dbm / 10;
|
||||
let fp = dbm % 10;
|
||||
|
||||
for (let k = 0; k < ip; k++)
|
||||
res *= 10;
|
||||
for (let k = 0; k < fp; k++)
|
||||
res *= LOG10_MAGIC;
|
||||
|
||||
return int(res);
|
||||
}
|
||||
|
||||
function dbm2quality(dbm) {
|
||||
let quality = dbm;
|
||||
|
||||
if (quality < -110)
|
||||
quality = -110;
|
||||
else if (quality > -40)
|
||||
quality = -40;
|
||||
quality += 110;
|
||||
|
||||
return quality;
|
||||
}
|
||||
|
||||
function hwmodelist(name) {
|
||||
const mode = { 'HT*': 'n', 'VHT*': 'ac', 'HE*': 'ax' };
|
||||
let iface = ifaces[name];
|
||||
let phy = board_data.wlan?.['phy' + iface.wiphy];
|
||||
if (!phy || !iface.radio?.band)
|
||||
return '';
|
||||
let htmodes = phy.info.bands[uc(iface.radio.band)].modes;
|
||||
let list = [];
|
||||
if (iface.radio.band == '2g' && 'NOHT' in htmodes)
|
||||
push(list, 'g/b');
|
||||
for (let k, v in mode)
|
||||
for (let htmode in htmodes)
|
||||
if (wildcard(htmode, k))
|
||||
push(list, v);
|
||||
|
||||
return join('/', reverse(uniq(list)));
|
||||
}
|
||||
|
||||
export function assoclist(dev) {
|
||||
let stations = ifaces[dev].assoclist;
|
||||
let ret = {};
|
||||
|
||||
for (let station in stations) {
|
||||
let sta = {
|
||||
mac: uc(station.mac),
|
||||
signal: station.sta_info.signal_avg,
|
||||
noise: ifaces[dev].noise,
|
||||
snr: station.sta_info.signal_avg - ifaces[dev].noise,
|
||||
inactive_time: station.sta_info.inactive_time,
|
||||
rx: {
|
||||
bitrate: format_rate(station.sta_info.rx_bitrate?.bitrate ?? 0),
|
||||
bitrate_raw: station.sta_info.rx_bitrate?.bitrate ?? 0,
|
||||
packets: station.sta_info.rx_packets ?? 0,
|
||||
flags: assoc_flags(station.sta_info.rx_bitrate ?? {}),
|
||||
},
|
||||
tx: {
|
||||
bitrate: format_rate(station.sta_info.tx_bitrate?.bitrate ?? 0),
|
||||
bitrate_raw: station.sta_info.tx_bitrate?.bitrate ?? 0,
|
||||
packets: station.sta_info.tx_packets ?? 0,
|
||||
flags: assoc_flags(station.sta_info.tx_bitrate ?? {}),
|
||||
},
|
||||
expected_throughput: station.sta_info.expected_throughput ?? 'unknown',
|
||||
};
|
||||
ret[sta.mac] = sta;
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
export function freqlist(name) {
|
||||
const freq_flags = {
|
||||
no_10mhz: 'NO_10MHZ',
|
||||
no_20mhz: 'NO_20MHZ',
|
||||
no_ht40_minus: 'NO_HT40-',
|
||||
no_ht40_plus: 'NO_HT40+',
|
||||
no_80mhz: 'NO_80MHZ',
|
||||
no_160mhz: 'NO_160MHZ',
|
||||
indoor_only: 'INDOOR_ONLY',
|
||||
no_ir: 'NO_IR',
|
||||
no_he: 'NO_HE',
|
||||
radar: 'RADAR_DETECTION',
|
||||
};
|
||||
|
||||
let iface = ifaces[name];
|
||||
let phy = find_phy(iface.wiphy);
|
||||
let channels = [];
|
||||
|
||||
for (let k, band in phy.wiphy_bands) {
|
||||
if (!band)
|
||||
continue;
|
||||
|
||||
let band_name = format_band(band.freqs[0].freq);
|
||||
for (let freq in band.freqs) {
|
||||
if (freq.disabled)
|
||||
continue;
|
||||
|
||||
let channel = {
|
||||
freq: format_frequency(freq.freq),
|
||||
band: band_name,
|
||||
channel: format_channel(freq.freq),
|
||||
flags: [],
|
||||
active: iface.wiphy_freq == freq.freq,
|
||||
};
|
||||
|
||||
for (let k, v in freq_flags)
|
||||
if (freq[k])
|
||||
push(channel.flags, v);
|
||||
|
||||
push(channels, channel);
|
||||
}
|
||||
}
|
||||
|
||||
return channels;
|
||||
};
|
||||
|
||||
export function info(name) {
|
||||
let order = [];
|
||||
for (let iface, data in ifaces)
|
||||
push(order, iface);
|
||||
|
||||
let list = [];
|
||||
for (let iface in sort(order)) {
|
||||
if (name && iface != name)
|
||||
continue;
|
||||
let data = ifaces[iface];
|
||||
let dev = {
|
||||
iface,
|
||||
ssid: data.ssid,
|
||||
mac: data.mac,
|
||||
mode: data.mode,
|
||||
channel: format_channel(data.wiphy_freq),
|
||||
freq: format_frequency(data.wiphy_freq),
|
||||
htmode: data.radio?.htmode,
|
||||
center_freq1: format_channel(data.center_freq1) || 'unknown',
|
||||
center_freq2: format_channel(data.center_freq2) || 'unknown',
|
||||
txpower: data.wiphy_tx_power_level / 100,
|
||||
noise: data.noise,
|
||||
signal: 0,
|
||||
bitrate: 0,
|
||||
encryption: 'unknown',
|
||||
hwmode: hwmodelist(iface),
|
||||
phy: 'phy' + data.wiphy,
|
||||
vaps: 'no',
|
||||
hw_type: data.hardware.type,
|
||||
hw_id: data.hardware.id,
|
||||
power_offset: data.hardware.power_offset || 'none',
|
||||
channel_offset: data.hardware.channel_offset || 'none',
|
||||
};
|
||||
|
||||
let phy = find_phy(data.wiphy);
|
||||
for (let limit in phy.interface_combinations[0]?.limits)
|
||||
if (limit.types?.ap && limit.max > 1)
|
||||
dev.vaps = 'yes';
|
||||
|
||||
if (data.bss_info) {
|
||||
if (data.bss_info.wpa_key_mgmt && data.bss_info.wpa_pairwise)
|
||||
dev.encryption = `${replace(data.bss_info.wpa_key_mgmt, ' ', ' / ')} (${data.bss_info.wpa_pairwise})`;
|
||||
else if (data.owe_transition_ifname)
|
||||
dev.encryption = 'none (OWE transition)';
|
||||
else
|
||||
dev.encryption = 'none';
|
||||
}
|
||||
|
||||
let stations = assoclist(iface);
|
||||
for (let k, station in stations) {
|
||||
dev.signal += station.signal;
|
||||
dev.bitrate += station.tx.bitrate_raw;
|
||||
}
|
||||
dev.signal /= length(data.assoclist) || 1;
|
||||
dev.bitrate /= length(data.assoclist) || 1;
|
||||
dev.bitrate = format_rate(dev.bitrate);
|
||||
dev.quality = dbm2quality(dev.signal);
|
||||
|
||||
if (data.owe_transition_ifname)
|
||||
dev.owe_transition_ifname = data.owe_transition_ifname;
|
||||
|
||||
push(list, dev);
|
||||
}
|
||||
|
||||
return list;
|
||||
};
|
||||
|
||||
export function htmodelist(name) {
|
||||
let iface = ifaces[name];
|
||||
let phy = board_data.wlan?.['phy' + iface.wiphy];
|
||||
if (!phy || !iface.radio.band)
|
||||
return [];
|
||||
|
||||
return filter(phy.info.bands[uc(iface.radio.band)].modes, (v) => v != 'NOHT');
|
||||
};
|
||||
|
||||
export function txpowerlist(name) {
|
||||
let iface = ifaces[name];
|
||||
let max_power = iface.max_power / 100;
|
||||
let match = iface.wiphy_tx_power_level / 100;
|
||||
let list = [];
|
||||
|
||||
for (let power = 0; power <= max_power; power++) {
|
||||
let txpower = {
|
||||
dbm: power,
|
||||
mw: dbm2mw(power),
|
||||
active: power == match,
|
||||
};
|
||||
push(list, txpower);
|
||||
}
|
||||
|
||||
return list;
|
||||
};
|
||||
|
||||
export function countrylist(dev) {
|
||||
let iface = ifaces[dev];
|
||||
|
||||
let list = {
|
||||
active: iface.country,
|
||||
countries,
|
||||
};
|
||||
|
||||
return list;
|
||||
};
|
||||
|
||||
function scan_extension(ext, cell) {
|
||||
const eht_chan_width = [ '20 MHz', '40 MHz', '80 MHz', '160 MHz', '320 MHz'];
|
||||
|
||||
switch(ord(ext, 0)) {
|
||||
case 36:
|
||||
let offset = 7;
|
||||
|
||||
if (!(ord(ext, 3) & 0x2))
|
||||
break;
|
||||
|
||||
if (ord(ext, 2) & 0x40)
|
||||
offset += 3;
|
||||
|
||||
if (ord(ext, 2) & 0x80)
|
||||
offset += 1;
|
||||
|
||||
cell.he = {
|
||||
chan_width: eht_chan_width[ord(ext, offset + 1) & 0x3],
|
||||
center_chan_1: ord(ext, offset + 2),
|
||||
center_chan_2: ord(ext, offset + 3),
|
||||
};
|
||||
break;
|
||||
|
||||
case 106:
|
||||
if (!(ord(ext, 1) & 0x1))
|
||||
break;
|
||||
|
||||
cell.eht = {
|
||||
chan_width: eht_chan_width[ord(ext, 6) & 0x7],
|
||||
center_chan_1: ord(ext, 7),
|
||||
center_chan_2: ord(ext, 8),
|
||||
};
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
export function scan(dev) {
|
||||
const rsn_cipher = [ 'NONE', 'WEP-40', 'TKIP', 'WRAP', 'CCMP', 'WEP-104', 'AES-OCB', 'CKIP', 'GCMP', 'GCMP-256', 'CCMP-256' ];
|
||||
const ht_chan_offset = [ 'no secondary', 'above', '[reserved]', 'below' ];
|
||||
const vht_chan_width = [ '20 or 40 MHz', '80 MHz', '80+80 MHz', '160 MHz' ];
|
||||
const ht_chan_width = [ '20 MHz', '40 MHz or higher' ];
|
||||
const SCAN_FLAG_AP = (1<<2);
|
||||
|
||||
let params = {
|
||||
dev,
|
||||
scan_flags: SCAN_FLAG_AP,
|
||||
scan_ssids: [ '' ],
|
||||
};
|
||||
|
||||
let res = nl80211.request(nl80211.const.NL80211_CMD_TRIGGER_SCAN, 0, params);
|
||||
if (res === false) {
|
||||
printf("Unable to trigger scan: " + nl80211.error() + "\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
res = nl80211.waitfor([
|
||||
nl80211.const.NL80211_CMD_NEW_SCAN_RESULTS,
|
||||
nl80211.const.NL80211_CMD_SCAN_ABORTED
|
||||
], 5000);
|
||||
|
||||
if (!res) {
|
||||
printf("Netlink error while awaiting scan results: " + nl80211.error() + "\n");
|
||||
exit(1);
|
||||
} else if (res.cmd == nl80211.const.NL80211_CMD_SCAN_ABORTED) {
|
||||
printf("Scan aborted by kernel\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
let scan = nl80211.request(nl80211.const.NL80211_CMD_GET_SCAN, nl80211.const.NLM_F_DUMP, { dev });
|
||||
|
||||
let cells = [];
|
||||
for (let k, bss in scan) {
|
||||
bss = bss.bss;
|
||||
let cell = {
|
||||
bssid: uc(bss.bssid),
|
||||
frequency: format_frequency(bss.frequency),
|
||||
band: format_band(bss.frequency),
|
||||
channel: format_channel(bss.frequency),
|
||||
dbm: bss.signal_mbm / 100,
|
||||
|
||||
};
|
||||
|
||||
if (bss.capability & (1 << 1))
|
||||
cell.mode = 'Ad-Hoc';
|
||||
else if (bss.capability & (1 << 0))
|
||||
cell.mode = 'Master';
|
||||
else
|
||||
cell.mode = 'Mesh Point';
|
||||
|
||||
cell.quality = dbm2quality(cell.dbm);
|
||||
|
||||
for (let ie in bss.information_elements)
|
||||
switch(ie.type) {
|
||||
case 0:
|
||||
case 114:
|
||||
cell.ssid = ie.data;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
cell.country = substr(ie.data, 0, 2);
|
||||
break;
|
||||
|
||||
case 48:
|
||||
cell.crypto = {
|
||||
group: rsn_cipher[ord(ie.data, 5)] ?? '',
|
||||
pair: [],
|
||||
key_mgmt: [],
|
||||
};
|
||||
|
||||
let offset = 6;
|
||||
let count = ord(ie.data, offset);
|
||||
offset += 2;
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
let key = rsn_cipher[ord(ie.data, offset + 3)];
|
||||
if (key)
|
||||
push(cell.crypto.pair, key);
|
||||
offset += 4;
|
||||
}
|
||||
|
||||
count = ord(ie.data, offset);
|
||||
offset += 2;
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
let key = format_mgmt_key(ord(ie.data, offset + 3));
|
||||
if (key)
|
||||
push(cell.crypto.key_mgmt, key);
|
||||
offset += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case 61:
|
||||
cell.ht = {
|
||||
primary_channel: ord(ie.data, 0),
|
||||
secondary_chan_off: ht_chan_offset[ord(ie.data, 1) & 0x3],
|
||||
chan_width: ht_chan_width[(ord(ie.data, 1) & 0x4) >> 2],
|
||||
};
|
||||
break;
|
||||
|
||||
case 192:
|
||||
cell.vht = {
|
||||
chan_width: vht_chan_width[ord(ie.data, 0)],
|
||||
center_chan_1: ord(ie.data, 1),
|
||||
center_chan_2: ord(ie.data, 2),
|
||||
};
|
||||
break;
|
||||
|
||||
case 255:
|
||||
scan_extension(ie.data, cell);
|
||||
break;
|
||||
};
|
||||
|
||||
|
||||
|
||||
push(cells, cell);
|
||||
}
|
||||
|
||||
return cells;
|
||||
};
|
||||
@@ -1,518 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import * as libuci from 'uci';
|
||||
import { md5 } from 'digest';
|
||||
import * as fs from 'fs';
|
||||
|
||||
import { append, append_raw, append_value, append_vars, append_string_vars, comment, push_config, set_default, touch_file } from 'wifi.common';
|
||||
import * as netifd from 'wifi.netifd';
|
||||
import * as iface from 'wifi.iface';
|
||||
|
||||
function iface_setup(config) {
|
||||
switch(config.fixup) {
|
||||
case 'owe':
|
||||
config.ignore_broadcast_ssid = true;
|
||||
config.ssid = config.ssid + 'OWE';
|
||||
break;
|
||||
|
||||
case 'owe-transition':
|
||||
let ifname = config.ifname;
|
||||
config.ifname = config.owe_transition_ifname;
|
||||
config.owe_transition_ifname = ifname;
|
||||
config.owe_transition_ssid = config.ssid + 'OWE';
|
||||
config.encryption = 'none';
|
||||
config.ignore_broadcast_ssid = false;
|
||||
iface.prepare(config);
|
||||
break;
|
||||
}
|
||||
|
||||
comment('Setup interface: ' + config.ifname);
|
||||
|
||||
config.bridge = config.network_bridge;
|
||||
config.snoop_iface = config.network_ifname;
|
||||
if (!config.wds)
|
||||
config.wds_bridge = null;
|
||||
else
|
||||
config.wds_sta = true;
|
||||
|
||||
if (!config.idx)
|
||||
append('interface', config.ifname);
|
||||
else
|
||||
append('bss', config.ifname);
|
||||
|
||||
if (config.multicast_to_unicast || config.proxy_arp)
|
||||
config.ap_isolate = 1;
|
||||
|
||||
append('bssid', config.macaddr);
|
||||
config.ssid2 = config.ssid;
|
||||
config.wmm_enabled = 1;
|
||||
append_string_vars(config, [ 'ssid2' ]);
|
||||
|
||||
append_vars(config, [
|
||||
'ctrl_interface', 'ap_isolate', 'max_num_sta', 'ap_max_inactivity', 'airtime_bss_weight',
|
||||
'airtime_bss_limit', 'airtime_sta_weight', 'bss_load_update_period', 'chan_util_avg_period',
|
||||
'disassoc_low_ack', 'skip_inactivity_poll', 'ignore_broadcast_ssid', 'uapsd_advertisement_enabled',
|
||||
'utf8_ssid', 'multi_ap', 'multi_ap_vlanid', 'multi_ap_profile', 'tdls_prohibit', 'bridge',
|
||||
'wds_sta', 'wds_bridge', 'snoop_iface', 'vendor_elements', 'nas_identifier', 'radius_acct_interim_interval',
|
||||
'ocv', 'multicast_to_unicast', 'preamble', 'proxy_arp', 'per_sta_vif', 'mbo',
|
||||
'bss_transition', 'wnm_sleep_mode', 'wnm_sleep_mode_no_keys', 'qos_map_set', 'max_listen_int',
|
||||
'dtim_period', 'wmm_enabled', 'start_disabled',
|
||||
]);
|
||||
}
|
||||
|
||||
function iface_authentication_server(config) {
|
||||
for (let server in config.auth_server_addr) {
|
||||
append('auth_server_addr', server);
|
||||
append_vars(config, [ 'auth_server_port', 'auth_server_shared_secret' ]);
|
||||
}
|
||||
|
||||
append_vars(config, [ 'radius_auth_req_attr' ]);
|
||||
}
|
||||
|
||||
function iface_accounting_server(config) {
|
||||
for (let server in config.acct_server_addr) {
|
||||
append('acct_server_addr', server);
|
||||
append_vars(config, [ 'acct_server_port', 'acct_server_shared_secret' ]);
|
||||
}
|
||||
|
||||
append_vars(config, [ 'radius_acct_req_attr' ]);
|
||||
}
|
||||
|
||||
function iface_auth_type(config) {
|
||||
if (config.auth_type in [ 'sae', 'owe', 'eap2', 'eap192' ]) {
|
||||
config.ieee80211w = 2;
|
||||
config.sae_require_mfp = 1;
|
||||
config.sae_pwe = 2;
|
||||
}
|
||||
|
||||
if (config.auth_type in [ 'psk-sae', 'eap-eap2' ]) {
|
||||
config.ieee80211w = 1;
|
||||
if (config.rsn_override)
|
||||
config.rsn_override_mfp = 2;
|
||||
config.sae_require_mfp = 1;
|
||||
config.sae_pwe = 2;
|
||||
}
|
||||
|
||||
if (config.own_ip_addr)
|
||||
config.dynamic_own_ip_addr = null;
|
||||
|
||||
if (!config.wpa)
|
||||
config.wpa_disable_eapol_key_retries = null;
|
||||
|
||||
switch(config.auth_type) {
|
||||
case 'none':
|
||||
case 'owe':
|
||||
config.wps_possible = 1;
|
||||
config.wps_state = 1;
|
||||
|
||||
append_string_vars(config, [ 'owe_transition_ssid' ]);
|
||||
append_vars(config, [
|
||||
'owe_transition_bssid', 'owe_transition_ifname',
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'psk':
|
||||
case 'psk2':
|
||||
case 'sae':
|
||||
case 'psk-sae':
|
||||
config.vlan_possible = 1;
|
||||
config.wps_possible = 1;
|
||||
|
||||
if (config.auth_type == 'psk' && config.ppsk) {
|
||||
iface_authentication_server(config);
|
||||
config.macaddr_acl = 2;
|
||||
config.wpa_psk_radius = 2;
|
||||
} else if (length(config.key) == 64) {
|
||||
config.wpa_psk = key;
|
||||
} else if (length(config.key) >= 8) {
|
||||
config.wpa_passphrase = config.key;
|
||||
} else if (!config.wpa_psk_file) {
|
||||
netifd.setup_failed('INVALID_WPA_PSK');
|
||||
}
|
||||
|
||||
set_default(config, 'wpa_psk_file', `/var/run/hostapd-${config.ifname}.psk`);
|
||||
touch_file(config.wpa_psk_file);
|
||||
break;
|
||||
|
||||
case 'eap':
|
||||
case 'eap2':
|
||||
case 'eap-eap2':
|
||||
case 'eap192':
|
||||
config.vlan_possible = 1;
|
||||
|
||||
if (config.fils) {
|
||||
set_default(config, 'erp_domain', substr(md5(config.ssid), 0, 4));
|
||||
set_default(config, 'fils_realm', config.erp_domain);
|
||||
set_default(config, 'erp_send_reauth_start', 1);
|
||||
set_default(config, 'fils_cache_id', substr(md5(config.fils_realm), 0, 4));
|
||||
}
|
||||
|
||||
if (!config.eap_server) {
|
||||
iface_authentication_server(config);
|
||||
iface_accounting_server(config);
|
||||
}
|
||||
|
||||
if (config.radius_das_client && config.radius_das_secret) {
|
||||
set_default(config, 'radius_das_port', 3799);
|
||||
set_default(config, 'radius_das_client', `${config.radius_das_client} ${config.radius_das_secret}`);
|
||||
}
|
||||
|
||||
set_default(config, 'eapol_version', config.wpa & 1);
|
||||
if (!config.eapol_version)
|
||||
config.eapol_version = null;
|
||||
append('eapol_key_index_workaround', '1');
|
||||
append('ieee8021x', '1');
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
append_vars(config, [
|
||||
'sae_require_mfp', 'sae_pwe', 'time_advertisement', 'time_zone',
|
||||
'wpa_group_rekey', 'wpa_ptk_rekey', 'wpa_gmk_rekey', 'wpa_strict_rekey',
|
||||
'macaddr_acl', 'wpa_psk_radius', 'wpa_psk', 'wpa_passphrase', 'wpa_psk_file',
|
||||
'eapol_version', 'dynamic_vlan', 'radius_request_cui', 'eap_reauth_period',
|
||||
'radius_das_client', 'radius_das_port', 'own_ip_addr', 'dynamic_own_ip_addr',
|
||||
'wpa_disable_eapol_key_retries', 'auth_algs', 'wpa', 'wpa_pairwise',
|
||||
'erp_domain', 'fils_realm', 'erp_send_reauth_start', 'fils_cache_id'
|
||||
]);
|
||||
}
|
||||
|
||||
function iface_ppsk(config) {
|
||||
if (!(config.auth_type in [ 'none', 'owe', 'psk', 'sae', 'psk-sae', 'wep' ]) || !config.auth_server_addr)
|
||||
return;
|
||||
|
||||
iface_authentication_server(config);
|
||||
append('macaddr_acl', '2');
|
||||
}
|
||||
|
||||
function iface_wps(config) {
|
||||
push_config(config, 'config_methods', 'wps_pushbutton', 'push_button');
|
||||
push_config(config, 'config_methods', 'wps_label', 'label');
|
||||
|
||||
if (config.multi_ap == 1)
|
||||
config.wps_possible = false;
|
||||
|
||||
if (config.wps_possible && length(config.config_methods)) {
|
||||
config.eap_server = 1;
|
||||
set_default(config, 'wps_state', 2);
|
||||
|
||||
if (config.ext_registrar && config.network_bridge)
|
||||
set_default(config, 'upnp_iface', config.network_bridge);
|
||||
|
||||
if (config.multi_ap && config.multi_ap_backhaul_ssid) {
|
||||
append_string_vars(config, [ 'multi_ap_backhaul_ssid' ]);
|
||||
if (length(config.multi_ap_backhaul_key) == 64)
|
||||
append('multi_ap_backhaul_wpa_psk', config.multi_ap_backhaul_key);
|
||||
else if (length(config.multi_ap_backhaul_key) > 8)
|
||||
append('multi_ap_backhaul_wpa_passphrase', config.multi_ap_backhaul_key);
|
||||
else
|
||||
netifd.setup_failed('INVALID_WPA_PSK');
|
||||
}
|
||||
|
||||
append_vars(config, [
|
||||
'wps_state', 'device_type', 'device_name', 'config_methods', 'wps_independent', 'eap_server',
|
||||
'ap_pin', 'ap_setup_locked', 'upnp_iface'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
function iface_rrm(config) {
|
||||
set_default(config, 'rrm_neighbor_report', config.ieee80211k);
|
||||
set_default(config, 'rrm_beacon_report', config.ieee80211k);
|
||||
|
||||
append_vars(config, [
|
||||
'rrm_neighbor_report', 'rrm_beacon_report', 'rnr', 'ftm_responder',
|
||||
]);
|
||||
}
|
||||
|
||||
function iface_ftm(config, phy_features) {
|
||||
if (!phy_features.ftm_responder || !config.ftm_responder)
|
||||
return;
|
||||
|
||||
append_vars(config, [
|
||||
'ftm_responder', 'lci', 'civic'
|
||||
]);
|
||||
}
|
||||
|
||||
function iface_macfilter(config) {
|
||||
let path = `/var/run/hostapd-${config.ifname}.maclist`;
|
||||
|
||||
switch(config.macfilter) {
|
||||
case 'allow':
|
||||
append('accept_mac_file', path);
|
||||
append('macaddr_acl', 1);
|
||||
config.vlan_possible = 1;
|
||||
break;
|
||||
|
||||
case 'deny':
|
||||
append('deny_mac_file', path);
|
||||
append('macaddr_acl', 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
let file = fs.open(path, 'w');
|
||||
if (!file) {
|
||||
warn(`Failed to open ${path}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (config.maclist)
|
||||
file.write(join('\n', config.maclist));
|
||||
|
||||
let macfile = fs.readfile(config.macfile);
|
||||
if (macfile)
|
||||
file.write(macfile);
|
||||
file.close();
|
||||
}
|
||||
|
||||
function iface_vlan(interface, config, vlans) {
|
||||
let path = `/var/run/hostapd-${config.ifname}.vlan`;
|
||||
|
||||
let file = fs.open(path, 'w');
|
||||
for (let k, vlan in vlans)
|
||||
if (vlan.config.name && vlan.config.vid) {
|
||||
let ifname = `${config.ifname}-${vlan.config.name}`;
|
||||
file.write(`${vlan.config.vid} ${ifname}\n`);
|
||||
netifd.set_vlan(interface, k, ifname);
|
||||
}
|
||||
file.close();
|
||||
|
||||
set_default(config, 'vlan_file', path);
|
||||
append_vars(config, [ 'vlan_file' ]);
|
||||
|
||||
if (!config.vlan_possible || !config.dynamic_vlan)
|
||||
return;
|
||||
|
||||
set_default(config, 'vlan_no_bridge', !config.vlan_bridge);
|
||||
|
||||
append_vars(config, [
|
||||
'dynamic_vlan', 'vlan_naming', 'vlan_bridge', 'vlan_no_bridge',
|
||||
'vlan_tagged_interface'
|
||||
]);
|
||||
}
|
||||
|
||||
function iface_stations(config, stas) {
|
||||
if (!length(stas))
|
||||
return;
|
||||
|
||||
let path = `/var/run/hostapd-${config.ifname}.psk`;
|
||||
|
||||
let file = fs.open(path, 'w');
|
||||
for (let k, sta in stas)
|
||||
if (sta.config.mac && sta.config.key) {
|
||||
let station = `${sta.config.mac} ${sta.config.key}\n`;
|
||||
if (sta.config.vid)
|
||||
station = `vlanid=${sta.config.vid} ` + station;
|
||||
file.write(station);
|
||||
}
|
||||
file.close();
|
||||
|
||||
set_default(config, 'wpa_psk_file', path);
|
||||
}
|
||||
|
||||
function iface_eap_server(config) {
|
||||
if (!config.eap_server)
|
||||
return;
|
||||
|
||||
set_default(config, 'eap_server', true);
|
||||
set_default(config, 'eap_server_erp', true);
|
||||
|
||||
append_vars(config, [
|
||||
'eap_server', 'eap_server_erp', 'eap_user_file', 'ca_cert', 'server_cert',
|
||||
'private_key', 'private_key_passwd', 'server_id',
|
||||
]);
|
||||
}
|
||||
|
||||
function iface_roaming(config) {
|
||||
if (!config.ieee80211r || config.wpa < 2)
|
||||
return;
|
||||
|
||||
set_default(config, 'mobility_domain', substr(md5(config.ssid), 0, 4));
|
||||
set_default(config, 'ft_psk_generate_local', config.auth_type == 'psk');
|
||||
set_default(config, 'ft_iface', config.network_ifname);
|
||||
|
||||
if (!config.ft_psk_generate_local) {
|
||||
if (!config.r0kh || !config.r1kh) {
|
||||
if (!config.auth_secret && !config.key)
|
||||
netifd.setup_failed('FT_KEY_CANT_BE_DERIVED');
|
||||
|
||||
let ft_key = md5(`${config.mobility_domain}/${config.auth_secret ?? config.key}`);
|
||||
|
||||
set_default(config, 'r0kh', [ 'ff:ff:ff:ff:ff:ff,*,' + ft_key ]);
|
||||
set_default(config, 'r1kh', [ '00:00:00:00:00:00,00:00:00:00:00:00,' + ft_key ]);
|
||||
}
|
||||
|
||||
for (let name in [ 'r0kh', 'r1kh' ])
|
||||
for (let val in config[name])
|
||||
append(name, join(' ', split(val, ',', 3)));
|
||||
|
||||
append_vars(config, [
|
||||
'r1_key_holder', 'r0_key_lifetime', 'pmk_r1_push'
|
||||
]);
|
||||
}
|
||||
|
||||
append_vars(config, [
|
||||
'mobility_domain', 'ft_psk_generate_local', 'ft_over_ds', 'reassociation_deadline',
|
||||
'ft_iface'
|
||||
]);
|
||||
}
|
||||
|
||||
function iface_mfp(config) {
|
||||
if (!config.ieee80211w || config.wpa < 2) {
|
||||
append('ieee80211w', 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (config.auth_type == 'eap192')
|
||||
config.group_mgmt_cipher = 'BIP-GMAC-256';
|
||||
else
|
||||
config.group_mgmt_cipher = config.ieee80211w_mgmt_cipher ?? 'AES-128-CMAC';
|
||||
|
||||
append_vars(config, [
|
||||
'ieee80211w', 'group_mgmt_cipher', 'assoc_sa_query_max_timeout', 'assoc_sa_query_retry_timeout'
|
||||
]);
|
||||
}
|
||||
|
||||
function iface_key_caching(config) {
|
||||
if (config.wpa < 2)
|
||||
return;
|
||||
|
||||
if (config.network_bridge && config.rsn_preauth) {
|
||||
set_default(config, 'okc', true);
|
||||
config.rsn_preauth_interfaces = config.network_bridge;
|
||||
|
||||
append_vars(config, [
|
||||
'rsn_preauth', 'rsn_preauth_interfaces'
|
||||
]);
|
||||
} else {
|
||||
set_default(config, 'okc', (config.auth_type in [ 'sae', 'psk-sae', 'owe' ]));
|
||||
}
|
||||
|
||||
if (!config.okc && !config.fils)
|
||||
config.disable_pmksa_caching = 1;
|
||||
|
||||
append_vars(config, [
|
||||
'okc', 'disable_pmksa_caching'
|
||||
]);
|
||||
}
|
||||
|
||||
function iface_hs20(config) {
|
||||
if (!config.hs20)
|
||||
return;
|
||||
|
||||
append_vars(config, [
|
||||
'hs20', 'disable_dgaf', 'anqp_domain_id', 'hs20_deauth_req_timeout',
|
||||
'hs20_wan_metrics', 'hs20_operating_class', 'hs20_t_c_filename', 'hs20_t_c_timestamp',
|
||||
'hs20_t_c_server_url', 'hs20_conn_capab'
|
||||
]);
|
||||
}
|
||||
|
||||
function iface_interworking(config) {
|
||||
if (!config.iw_enabled)
|
||||
return;
|
||||
|
||||
config.interworking = true;
|
||||
|
||||
if (config.domain_name)
|
||||
config.domain_name = join(',', config.domain_name);
|
||||
|
||||
if (config.anqp_3gpp_cell_net)
|
||||
config.domain_name = join(',', config.anqp_3gpp_cell_net);
|
||||
|
||||
append_vars(config, [
|
||||
'interworking', 'internet', 'asra', 'uesa', 'access_network_type', 'hessid', 'venue_group',
|
||||
'venue_type', 'network_auth_type', 'gas_address3', 'roaming_consortium', 'anqp_elem', 'nai_realm',
|
||||
'venue_name', 'venue_url', 'domain_name', 'anqp_3gpp_cell_net',
|
||||
]);
|
||||
}
|
||||
|
||||
export function generate(interface, data, config, vlans, stas, phy_features) {
|
||||
config.ctrl_interface = '/var/run/hostapd';
|
||||
|
||||
iface_stations(config, stas);
|
||||
|
||||
config.start_disabled = data.ap_start_disabled;
|
||||
iface_setup(config);
|
||||
|
||||
iface.parse_encryption(config, data.config);
|
||||
if (data.config.band == '6g') {
|
||||
if (config.auth_type == 'psk-sae')
|
||||
config.auth_type = 'sae';
|
||||
if (config.auth_type == 'eap-eap2')
|
||||
config.auth_type = 'eap2';
|
||||
}
|
||||
|
||||
iface_auth_type(config);
|
||||
|
||||
iface_accounting_server(config);
|
||||
|
||||
iface_ppsk(config);
|
||||
|
||||
iface_wps(config);
|
||||
|
||||
iface_rrm(config);
|
||||
|
||||
iface_ftm(config, phy_features);
|
||||
|
||||
iface_macfilter(config);
|
||||
|
||||
iface_vlan(interface, config, vlans);
|
||||
|
||||
iface_eap_server(config);
|
||||
|
||||
iface_roaming(config);
|
||||
|
||||
iface_mfp(config);
|
||||
|
||||
iface_key_caching(config);
|
||||
|
||||
iface_hs20(config);
|
||||
|
||||
iface_interworking(config);
|
||||
|
||||
iface.wpa_key_mgmt(config);
|
||||
append_vars(config, [
|
||||
'wpa_key_mgmt',
|
||||
]);
|
||||
|
||||
if (config.rsn_override_key_mgmt || config.rsn_override_pairwise) {
|
||||
config.rsn_override_mfp ??= config.ieee80211w;
|
||||
config.rsn_override_key_mgmt ??= config.wpa_key_mgmt;
|
||||
config.rsn_override_pairwise ??= config.wpa_pairwise;
|
||||
append_vars(config, [
|
||||
'rsn_override_key_mgmt',
|
||||
'rsn_override_pairwise',
|
||||
'rsn_override_mfp'
|
||||
]);
|
||||
|
||||
if (config.mlo) {
|
||||
config.rsn_override_mfp_2 ??= config.rsn_override_mfp;
|
||||
config.rsn_override_key_mgmt_2 ??= config.rsn_override_key_mgmt;
|
||||
config.rsn_override_pairwise_2 ??= config.rsn_override_pairwise;
|
||||
|
||||
append_vars(config, [
|
||||
'rsn_override_key_mgmt_2',
|
||||
'rsn_override_pairwise_2',
|
||||
'rsn_override_mfp_2'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/* raw options */
|
||||
for (let raw in config.hostapd_options)
|
||||
append_raw(raw);
|
||||
|
||||
if (config.mlo) {
|
||||
append_raw('mld_ap=1');
|
||||
if (data.config.radio != null)
|
||||
append_raw('mld_link_id=' + data.config.radio);
|
||||
}
|
||||
|
||||
if (config.default_macaddr)
|
||||
append_raw('#default_macaddr');
|
||||
else if (config.random_macaddr)
|
||||
append_raw('#random_macaddr');
|
||||
};
|
||||
@@ -1,174 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import * as libubus from 'ubus';
|
||||
import * as nl80211 from 'nl80211';
|
||||
import * as fs from 'fs';
|
||||
|
||||
global.ubus = libubus.connect();
|
||||
|
||||
let config_data = '';
|
||||
let network_data = '';
|
||||
|
||||
const nl80211_bands = [ '2g', '5g', '60g', '6g' ];
|
||||
|
||||
export function wiphy_info(phy) {
|
||||
let idx = +fs.readfile(`/sys/class/ieee80211/${phy}/index`);
|
||||
|
||||
return nl80211.request(nl80211.const.NL80211_CMD_GET_WIPHY, nl80211.const.NLM_F_DUMP, {
|
||||
wiphy: idx,
|
||||
split_wiphy_dump: true
|
||||
});
|
||||
};
|
||||
|
||||
export function wiphy_band(info, band) {
|
||||
let band_idx = index(nl80211_bands, band);
|
||||
if (band_idx < 0 || !info)
|
||||
return;
|
||||
|
||||
return info.wiphy_bands[band_idx];
|
||||
};
|
||||
|
||||
export function log(msg) {
|
||||
printf(`wifi-scripts: ${msg}\n`);
|
||||
};
|
||||
|
||||
export function append_raw(value) {
|
||||
config_data += value + '\n';
|
||||
};
|
||||
|
||||
export function append(key, value) {
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
switch (type(value)) {
|
||||
case 'array':
|
||||
value = join(' ', value);
|
||||
break;
|
||||
case 'bool':
|
||||
value = value ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
append_raw(key + '=' + value);
|
||||
};
|
||||
|
||||
function escape_string(value) {
|
||||
let chars = map(split(value, ''), (v) => ord(v));
|
||||
if (length(filter(chars, (v) => (v < 32 || v >= 128))) > 0)
|
||||
return hexenc(value);
|
||||
|
||||
return `"${value}"`;
|
||||
}
|
||||
|
||||
export function append_string(key, value) {
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
append(key, escape_string(value));
|
||||
};
|
||||
|
||||
export function append_vars(dict, keys) {
|
||||
for (let key in keys)
|
||||
append(key, dict[key]);
|
||||
};
|
||||
|
||||
export function append_string_vars(dict, keys) {
|
||||
for (let key in keys)
|
||||
append_string(key, dict[key]);
|
||||
};
|
||||
|
||||
export function network_append_raw(value) {
|
||||
network_data += value + '\n';
|
||||
};
|
||||
|
||||
export function network_append(key, value) {
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
switch (type(value)) {
|
||||
case 'array':
|
||||
value = join(' ', value);
|
||||
break;
|
||||
case 'bool':
|
||||
value = value ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
network_append_raw('\t' + key + '=' + value);
|
||||
};
|
||||
|
||||
export function network_append_string(key, value) {
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
network_append_raw('\t' + key + '=' + escape_string(value));
|
||||
};
|
||||
|
||||
export function network_append_vars(dict, keys) {
|
||||
for (let key in keys)
|
||||
network_append(key, dict[key]);
|
||||
};
|
||||
|
||||
export function network_append_string_vars(dict, keys) {
|
||||
for (let key in keys)
|
||||
network_append_string(key, dict[key]);
|
||||
};
|
||||
|
||||
export function set_default(dict, key, value) {
|
||||
if (dict[key] == null)
|
||||
dict[key] = value;
|
||||
};
|
||||
|
||||
export function push_config(dict, key, option, value) {
|
||||
if (!dict[option])
|
||||
return;
|
||||
|
||||
dict[key] ??= [];
|
||||
push(dict[key], value);
|
||||
};
|
||||
|
||||
export function touch_file(filename) {
|
||||
let file = fs.open(filename, "a");
|
||||
if (file)
|
||||
file.close();
|
||||
else
|
||||
log('Failed to touch ' + filename);
|
||||
};
|
||||
|
||||
export function append_value(config, key, value) {
|
||||
if (!config[key])
|
||||
config[key] = value;
|
||||
else
|
||||
config[key] += ' ' + value;
|
||||
};
|
||||
|
||||
export function comment(comment) {
|
||||
append_raw('\n# ' + comment);
|
||||
};
|
||||
|
||||
export function dump_config(file) {
|
||||
if (file)
|
||||
fs.writefile(file, config_data);
|
||||
|
||||
return config_data;
|
||||
};
|
||||
|
||||
export function dump_network(file) {
|
||||
config_data += 'network={\n';
|
||||
config_data += network_data;;
|
||||
config_data += '}\n';
|
||||
|
||||
if (file)
|
||||
fs.writefile(file, config_data);
|
||||
|
||||
return config_data;
|
||||
};
|
||||
|
||||
export function flush_config() {
|
||||
config_data = '';
|
||||
};
|
||||
|
||||
export function flush_network() {
|
||||
config_data = '';
|
||||
network_data = '';
|
||||
};
|
||||
@@ -1,580 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import {
|
||||
append, append_raw, append_vars, dump_config, flush_config, set_default,
|
||||
wiphy_info, wiphy_band
|
||||
} from 'wifi.common';
|
||||
import { validate } from 'wifi.validate';
|
||||
import * as netifd from 'wifi.netifd';
|
||||
import * as iface from 'wifi.iface';
|
||||
import * as nl80211 from 'nl80211';
|
||||
import * as ap from 'wifi.ap';
|
||||
import * as fs from 'fs';
|
||||
|
||||
const NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER = 33;
|
||||
const NL80211_EXT_FEATURE_RADAR_BACKGROUND = 61;
|
||||
|
||||
let phy_features = {};
|
||||
let phy_capabilities = {};
|
||||
|
||||
/* make sure old style UCI and hwmode and newer band properties are correctly resolved */
|
||||
function set_device_defaults(config) {
|
||||
/* validate the hw mode */
|
||||
if (config.hw_mode in [ '11a', '11b', '11g', '11ad' ])
|
||||
config.hw_mode = substr(config.hw_mode, 2);
|
||||
else if (config.channel > 14)
|
||||
config.hw_mode = 'a';
|
||||
else
|
||||
config.hw_mode = 'g';
|
||||
|
||||
/* validate band */
|
||||
if (config.band == '2g')
|
||||
config.hw_mode = 'g';
|
||||
else if (config.band in [ '5g', '6g', '60g' ])
|
||||
config.hw_mode = 'a';
|
||||
else
|
||||
switch (config.hw_mode) {
|
||||
case 'a':
|
||||
config.band = '5g';
|
||||
break;
|
||||
|
||||
case 'ad':
|
||||
config.band = '60g';
|
||||
break;
|
||||
|
||||
default:
|
||||
config.band = '2g';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* setup sylog / stdout */
|
||||
function device_log_append(config) {
|
||||
let log_mask = 0;
|
||||
|
||||
for (let k in [ 'log_mlme', 'log_iapp', 'log_driver', 'log_wpa', 'log_radius', 'log_8021x', 'log_80211' ]) {
|
||||
log_mask <<= 1;
|
||||
log_mask |= config[k] ? 1 : 0;
|
||||
}
|
||||
|
||||
append('logger_syslog', log_mask);
|
||||
append('logger_syslog_level', config.log_level);
|
||||
append('logger_stdout', log_mask);
|
||||
append('logger_stdout_level', config.log_level);
|
||||
}
|
||||
|
||||
/* setup country code */
|
||||
function device_country_code(config) {
|
||||
let status = global.ubus.call('network.wireless', 'status');
|
||||
for (let name, radio in status) {
|
||||
if (!radio.config.country)
|
||||
continue;
|
||||
config.country_code = radio.config.country;
|
||||
}
|
||||
|
||||
if (!exists(config, 'country_code'))
|
||||
return;
|
||||
|
||||
if (config.hw_mode != 'a')
|
||||
delete config.ieee80211h;
|
||||
append_vars(config, [ 'country_code', 'country3', 'ieee80211h' ]);
|
||||
if (config.ieee80211d)
|
||||
append_vars(config, [ 'ieee80211d', 'local_pwr_constraint', 'spectrum_mgmt_required' ]);
|
||||
}
|
||||
|
||||
|
||||
/* setup cell density */
|
||||
function device_cell_density_append(config) {
|
||||
switch (config.hw_mode) {
|
||||
case 'b':
|
||||
if (config.cell_density == 1) {
|
||||
config.supported_rates ??= [ 5500, 11000 ];
|
||||
config.basic_rates ??= [ 5500, 11000 ];
|
||||
} else if (config.cell_density > 2) {
|
||||
config.supported_rates ??= [ 11000 ];
|
||||
config.basic_rates ??= [ 11000 ];
|
||||
}
|
||||
;;
|
||||
case 'g':
|
||||
if (config.cell_density in [ 0, 1 ]) {
|
||||
if (!config.legacy_rates) {
|
||||
config.supported_rates ??= [ 6000, 9000, 12000, 18000, 24000, 36000, 48000, 54000 ];
|
||||
config.basic_rates ??= [ 6000, 12000, 24000 ];
|
||||
} else if (config.cell_density == 1) {
|
||||
config.supported_rates ??= [ 5500, 6000, 9000, 11000, 12000, 18000, 24000, 36000, 48000, 54000 ];
|
||||
config.basic_rates ??= [ 5500, 11000 ];
|
||||
}
|
||||
} else if (config.cell_density == 2 || (config.cell_density > 3 && config.legacy_rates)) {
|
||||
if (!config.legacy_rates) {
|
||||
config.supported_rates ??= [ 12000, 18000, 24000, 36000, 48000, 54000 ];
|
||||
config.basic_rates ??= [ 12000, 24000 ];
|
||||
} else {
|
||||
config.supported_rates ??= [ 11000, 12000, 18000, 24000, 36000, 48000, 54000 ];
|
||||
config.basic_rates ??= [ 11000 ];
|
||||
}
|
||||
} else if (config.cell_density > 2) {
|
||||
config.supported_rates ??= [ 24000, 36000, 48000, 54000 ];
|
||||
config.basic_rates ??= [ 24000 ];
|
||||
}
|
||||
;;
|
||||
case 'a':
|
||||
switch (config.cell_density) {
|
||||
case 1:
|
||||
config.supported_rates ??= [ 6000, 9000, 12000, 18000, 24000, 36000, 48000, 54000 ];
|
||||
config.basic_rates ??= [ 6000, 12000, 24000 ];
|
||||
break;
|
||||
|
||||
case 2:
|
||||
config.supported_rates ??= [ 12000, 18000, 24000, 36000, 48000, 54000 ];
|
||||
config.basic_rates ??= [ 12000, 24000 ];
|
||||
break;
|
||||
|
||||
case 3:
|
||||
config.supported_rates ??= [ 24000, 36000, 48000, 54000 ];
|
||||
config.basic_rates ??= [ 24000 ];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function device_rates(config) {
|
||||
for (let key in [ 'supported_rates', 'basic_rates' ])
|
||||
config[key] = map(config[key], x => x / 100);
|
||||
|
||||
append_vars(config, [ 'beacon_rate', 'supported_rates', 'basic_rates' ]);
|
||||
}
|
||||
|
||||
function device_htmode_append(config) {
|
||||
config.channel_offset = config.band == '6g' ? 1 : 0;
|
||||
|
||||
/* 802.11n */
|
||||
config.ieee80211n = 0;
|
||||
if (config.band != '6g') {
|
||||
if (config.htmode in [ 'VHT20', 'HT20', 'HE20', 'EHT20' ])
|
||||
config.ieee80211n = 1;
|
||||
if (config.htmode in [ 'HT40', 'HT40+', 'HT40-', 'VHT40', 'VHT80', 'VHT160', 'HE40', 'HE80', 'HE160', 'EHT40', 'EHT80', 'EHT160' ]) {
|
||||
config.ieee80211n = 1;
|
||||
if (!config.channel)
|
||||
config.ht_capab = '[HT40+]';
|
||||
else
|
||||
switch (config.hw_mode) {
|
||||
case 'a':
|
||||
switch (((config.channel / 4) + config.channel_offset) % 2) {
|
||||
case 0:
|
||||
config.ht_capab = '[HT40-]';
|
||||
break;
|
||||
|
||||
case 1:
|
||||
config.ht_capab = '[HT40+]';
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
switch (config.htmode) {
|
||||
case 'HT40+':
|
||||
case 'HT40-':
|
||||
config.ht_capab = '[' + config.htmode + ']';
|
||||
break;
|
||||
|
||||
default:
|
||||
if (config.channel < 7)
|
||||
config.ht_capab = '[HT40+]';
|
||||
else
|
||||
config.ht_capab = '[HT40-]';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.ieee80211n) {
|
||||
let ht_capab = phy_capabilities.ht_capa;
|
||||
|
||||
if (ht_capab & 0x1 && config.ldpc)
|
||||
config.ht_capab += '[LDPC]';
|
||||
if (ht_capab & 0x10 && config.greenfield)
|
||||
config.ht_capab += '[GF]';
|
||||
if (ht_capab & 0x20 && config.short_gi_20)
|
||||
config.ht_capab += '[SHORT-GI-20]';
|
||||
if (ht_capab & 0x40 && config.short_gi_40)
|
||||
config.ht_capab += '[SHORT-GI-40]';
|
||||
if (ht_capab & 0x80 && config.tx_stbc)
|
||||
config.ht_capab += '[TX-STBC]';
|
||||
if (ht_capab & 0x800 && config.max_amsdu)
|
||||
config.ht_capab += '[MAX-AMSDU-7935]';
|
||||
if (ht_capab & 0x1000 && config.dsss_cck_40)
|
||||
config.ht_capab += '[DSSS_CCK-40]';
|
||||
let rx_stbc = [ '', '[RX-STBC1]', '[RX-STBC12]', '[RX-STBC123]' ];
|
||||
config.ht_capab += rx_stbc[min(config.rx_stbc, (ht_capab >> 8) & 3)];
|
||||
|
||||
append_vars(config, [ 'ieee80211n', 'ht_coex', 'ht_capab' ]);
|
||||
}
|
||||
}
|
||||
|
||||
/* 802.11ac */
|
||||
config.ieee80211ac = 1;
|
||||
config.vht_oper_centr_freq_seg0_idx = 0;
|
||||
config.vht_oper_chwidth = 0;
|
||||
|
||||
switch (config.htmode) {
|
||||
case 'VHT20':
|
||||
case 'HE20':
|
||||
case 'EHT20':
|
||||
break;
|
||||
|
||||
case 'VHT40':
|
||||
case 'HE40':
|
||||
case 'EHT40':
|
||||
config.vht_oper_centr_freq_seg0_idx = config.channel + (((config.channel / 4) + config.channel_offset) % 2 ? 2 : -2);
|
||||
break;
|
||||
|
||||
case 'VHT80':
|
||||
case 'HE80':
|
||||
case 'EHT80':
|
||||
let delta = [ -6, 6, 2, -2 ];
|
||||
config.vht_oper_centr_freq_seg0_idx = config.channel + delta[((config.channel / 4) + config.channel_offset) % 4];
|
||||
config.vht_oper_chwidth = 1;
|
||||
break;
|
||||
|
||||
case 'VHT160':
|
||||
case 'HE160':
|
||||
case 'EHT160':
|
||||
let vht_oper_centr_freq_seg0_idx_map = [[ 64, 50 ], [ 128, 114 ], [ 177, 163 ]];
|
||||
if (config.band == '6g')
|
||||
vht_oper_centr_freq_seg0_idx_map = [
|
||||
[ 29, 15 ], [ 61, 47 ], [ 93, 79 ], [ 125, 111 ],
|
||||
[ 157, 143 ], [ 189, 175 ], [ 221, 207 ]];
|
||||
for (let k, v in vht_oper_centr_freq_seg0_idx_map)
|
||||
if (config.channel >= (v[0] - 28) && config.channel <= v[0]) {
|
||||
config.vht_oper_centr_freq_seg0_idx = v[1];
|
||||
break;
|
||||
}
|
||||
config.vht_oper_chwidth = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
config.ieee80211ac = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
config.eht_oper_chwidth = config.vht_oper_chwidth;
|
||||
config.eht_oper_centr_freq_seg0_idx = config.vht_oper_centr_freq_seg0_idx;
|
||||
|
||||
if (config.band == '6g') {
|
||||
config.ieee80211ac = 0;
|
||||
|
||||
switch(config.htmode) {
|
||||
case 'HE20':
|
||||
case 'EHT20':
|
||||
config.op_class = 131;
|
||||
break;
|
||||
|
||||
case 'EHT320':
|
||||
let eht_center_seg0_map = [
|
||||
[ 61, 31 ], [ 125, 95 ], [ 189, 159 ], [ 221, 191 ]
|
||||
];
|
||||
|
||||
for (let k, v in eht_center_seg0_map)
|
||||
if (config.channel <= v[0]) {
|
||||
config.eht_oper_centr_freq_seg0_idx = v[1];
|
||||
break;
|
||||
}
|
||||
config.op_class = 137;
|
||||
config.eht_oper_chwidth = 7;
|
||||
break;
|
||||
|
||||
case 'HE40':
|
||||
case 'HE80':
|
||||
case 'HE160':
|
||||
case 'EHT40':
|
||||
case 'EHT80':
|
||||
case 'EHT160':
|
||||
config.op_class = 132 + config.eht_oper_chwidth;
|
||||
break;
|
||||
}
|
||||
|
||||
append_vars(config, [ 'op_class' ]);
|
||||
}
|
||||
|
||||
if (config.ieee80211ac && config.hw_mode == 'a') {
|
||||
/* VHT capab */
|
||||
if (config.vht_oper_chwidth < 2) {
|
||||
config.vht160 = 0;
|
||||
config.short_gi_160 = 0;
|
||||
}
|
||||
|
||||
config.tx_queue_data2_burst = '2.0';
|
||||
|
||||
let vht_capab = phy_capabilities.vht_capa;
|
||||
|
||||
config.vht_capab = '';
|
||||
if (vht_capab & 0x10 && config.rxldpc)
|
||||
config.vht_capab += '[RXLDPC]';
|
||||
if (vht_capab & 0x20 && config.short_gi_80)
|
||||
config.vht_capab += '[SHORT-GI-80]';
|
||||
if (vht_capab & 0x40 && config.short_gi_160)
|
||||
config.vht_capab += '[SHORT-GI-160]';
|
||||
if (vht_capab & 0x80 && config.tx_stbc_2by1)
|
||||
config.vht_capab += '[TX-STBC-2BY1]';
|
||||
if (vht_capab & 0x800 && config.su_beamformer)
|
||||
config.vht_capab += '[SU-BEAMFORMER]';
|
||||
if (vht_capab & 0x1000 && config.su_beamformee)
|
||||
config.vht_capab += '[SU-BEAMFORMEE]';
|
||||
if (vht_capab & 0x80000 && config.mu_beamformer)
|
||||
config.vht_capab += '[MU-BEAMFORMER]';
|
||||
if (vht_capab & 0x100000 && config.mu_beamformee)
|
||||
config.vht_capab += '[MU-BEAMFORMEE]';
|
||||
if (vht_capab & 0x200000 && config.vht_txop_ps)
|
||||
config.vht_capab += '[VHT-TXOP-PS]';
|
||||
if (vht_capab & 0x400000 && config.htc_vht)
|
||||
config.vht_capab += '[HTC-VHT]';
|
||||
if (vht_capab & 0x10000000 && config.rx_antenna_pattern)
|
||||
config.vht_capab += '[RX-ANTENNA-PATTERN]';
|
||||
if (vht_capab & 0x20000000 && config.tx_antenna_pattern)
|
||||
config.vht_capab += '[TX-ANTENNA-PATTERN]';
|
||||
let rx_stbc = [ '', '[RX-STBC-1]', '[RX-STBC-12]', '[RX-STBC-123]', '[RX-STBC-1234]' ];
|
||||
config.vht_capab += rx_stbc[min(config.rx_stbc, (vht_capab >> 8) & 7)];
|
||||
|
||||
if (vht_capab & 0x800 && config.su_beamformer)
|
||||
config.vht_capab += '[SOUNDING-DIMENSION-' + min(((vht_capab >> 16) & 3) + 1, config.beamformer_antennas) + ']';
|
||||
if (vht_capab & 0x1000 && config.su_beamformee)
|
||||
config.vht_capab += '[BF-ANTENNA-' + min(((vht_capab >> 13) & 3) + 1, config.beamformer_antennas) + ']';
|
||||
|
||||
/* supported Channel widths */
|
||||
if ((vht_capab & 0xc) == 8 && config.vht160 <= 2)
|
||||
config.vht_capab += '[VHT160-80PLUS80]';
|
||||
else if ((vht_capab & 0xc) == 4 && config.vht160 <= 2)
|
||||
config.vht_capab += '[VHT160]';
|
||||
|
||||
/* maximum MPDU length */
|
||||
if ((vht_capab & 3) > 1 && config.vht_max_mpdu >= 11454)
|
||||
config.vht_capab += '[MAX-MPDU-11454]';
|
||||
else if ((vht_capab & 3) && config.vht_max_mpdu >= 7991)
|
||||
config.vht_capab += '[MAX-MPDU-7991]';
|
||||
|
||||
/* maximum A-MPDU length exponent */
|
||||
let max_a_mpdu_len_exp = (vht_capab >> 20) & 0x38;
|
||||
for (let exp = 7; exp; exp--)
|
||||
if (max_a_mpdu_len_exp >= (0x8 * exp) && exp <= config.vht_max_a_mpdu_len_exp) {
|
||||
config.vht_capab += '[MAX-A-MPDU-LEN-EXP' + exp + ']';
|
||||
break;
|
||||
}
|
||||
|
||||
/* whether or not the STA supports link adaptation using VHT variant */
|
||||
let vht_link_adapt = vht_capab & 0xC000000;
|
||||
if (vht_link_adapt >= 0xC000000 && config.vht_link_adapt > 3)
|
||||
config.vht_capab += '[VHT-LINK-ADAPT-3]';
|
||||
if (vht_link_adapt >= 0x8000000 && config.vht_link_adapt > 2)
|
||||
config.vht_capab += '[VHT-LINK-ADAPT-2]';
|
||||
|
||||
append_vars(config, [
|
||||
'ieee80211ac', 'vht_oper_chwidth', 'vht_oper_centr_freq_seg0_idx',
|
||||
'vht_capab'
|
||||
]);
|
||||
}
|
||||
|
||||
/* 802.11ax */
|
||||
if (wildcard(config.htmode, 'HE*') || wildcard(config.htmode, 'EHT*')) {
|
||||
let he_phy_cap = phy_capabilities.he_phy_cap;
|
||||
let he_mac_cap = phy_capabilities.he_mac_cap;
|
||||
|
||||
config.ieee80211ax = true;
|
||||
|
||||
if (config.hw_mode == 'a') {
|
||||
config.he_oper_chwidth = config.vht_oper_chwidth;
|
||||
config.he_oper_centr_freq_seg0_idx = config.vht_oper_centr_freq_seg0_idx;
|
||||
}
|
||||
|
||||
if (config.he_bss_color_enabled) {
|
||||
if (config.he_spr_non_srg_obss_pd_max_offset)
|
||||
config.he_spr_sr_control |= 1 << 2;
|
||||
if (!config.he_spr_psr_enabled)
|
||||
config.he_spr_sr_control |= 1;
|
||||
append_vars(config, [ 'he_bss_color', 'he_spr_non_srg_obss_pd_max_offset', 'he_spr_sr_control' ]);
|
||||
}
|
||||
|
||||
if (!(he_phy_cap[3] & 0x80))
|
||||
config.he_su_beamformer = false;
|
||||
if (!(he_phy_cap[4] & 0x1))
|
||||
config.he_su_beamformee = false;
|
||||
if (!(he_phy_cap[4] & 0x2))
|
||||
config.he_mu_beamformer = false;
|
||||
if (!(he_phy_cap[7] & 0x1))
|
||||
config.he_spr_psr_enabled = false;
|
||||
if (!(he_mac_cap[0] & 0x1))
|
||||
config.he_twt_required= false;
|
||||
|
||||
append_vars(config, [
|
||||
'ieee80211ax', 'he_oper_chwidth', 'he_oper_centr_freq_seg0_idx',
|
||||
'he_su_beamformer', 'he_su_beamformee', 'he_mu_beamformer', 'he_twt_required',
|
||||
'he_default_pe_duration', 'he_rts_threshold', 'he_mu_edca_qos_info_param_count',
|
||||
'he_mu_edca_qos_info_q_ack', 'he_mu_edca_qos_info_queue_request', 'he_mu_edca_qos_info_txop_request',
|
||||
'he_mu_edca_ac_be_aifsn', 'he_mu_edca_ac_be_aci', 'he_mu_edca_ac_be_ecwmin',
|
||||
'he_mu_edca_ac_be_ecwmax', 'he_mu_edca_ac_be_timer', 'he_mu_edca_ac_bk_aifsn',
|
||||
'he_mu_edca_ac_bk_aci', 'he_mu_edca_ac_bk_ecwmin', 'he_mu_edca_ac_bk_ecwmax',
|
||||
'he_mu_edca_ac_bk_timer', 'he_mu_edca_ac_vi_ecwmin', 'he_mu_edca_ac_vi_ecwmax',
|
||||
'he_mu_edca_ac_vi_aifsn', 'he_mu_edca_ac_vi_aci', 'he_mu_edca_ac_vi_timer',
|
||||
'he_mu_edca_ac_vo_aifsn', 'he_mu_edca_ac_vo_aci', 'he_mu_edca_ac_vo_ecwmin',
|
||||
'he_mu_edca_ac_vo_ecwmax', 'he_mu_edca_ac_vo_timer',
|
||||
]);
|
||||
}
|
||||
|
||||
if (wildcard(config.htmode, 'EHT*')) {
|
||||
config.ieee80211be = true;
|
||||
append_vars(config, [ 'ieee80211be' ]);
|
||||
|
||||
if (config.hw_mode == 'a')
|
||||
append_vars(config, [ 'eht_oper_chwidth', 'eht_oper_centr_freq_seg0_idx' ]);
|
||||
|
||||
if (config.band == "6g") {
|
||||
config.stationary_ap = true;
|
||||
append_vars(config, [ 'he_6ghz_reg_pwr_type', ]);
|
||||
}
|
||||
}
|
||||
|
||||
append_vars(config, [ 'tx_queue_data2_burst', 'stationary_ap' ]);
|
||||
}
|
||||
|
||||
function device_extended_features(data, flag) {
|
||||
return !!(data[flag / 8] | (1 << (flag % 8)));
|
||||
}
|
||||
|
||||
function device_capabilities(config) {
|
||||
let phy = config.phy;
|
||||
|
||||
phy = wiphy_info(phy);
|
||||
let band = wiphy_band(phy, config.band);
|
||||
|
||||
phy_capabilities.ht_capa = band.ht_capa ?? 0;
|
||||
phy_capabilities.vht_capa = band.vht_capa ?? 0;
|
||||
for (let iftype in band.iftype_data) {
|
||||
if (!iftype.iftypes.ap)
|
||||
continue;
|
||||
phy_capabilities.he_mac_cap = iftype.he_cap_mac;
|
||||
phy_capabilities.he_phy_cap = iftype.he_cap_phy;
|
||||
}
|
||||
|
||||
phy_features.ftm_responder = device_extended_features(phy.extended_features, NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
|
||||
phy_features.radar_background = device_extended_features(phy.extended_features, NL80211_EXT_FEATURE_RADAR_BACKGROUND);
|
||||
}
|
||||
|
||||
function generate(config) {
|
||||
if (!config)
|
||||
die(`${config.path} is an unknown phy`);
|
||||
|
||||
device_capabilities(config);
|
||||
|
||||
append('driver', 'nl80211');
|
||||
|
||||
set_device_defaults(config);
|
||||
|
||||
device_log_append(config);
|
||||
|
||||
device_country_code(config);
|
||||
|
||||
device_cell_density_append(config);
|
||||
|
||||
device_rates(config);
|
||||
|
||||
/* beacon */
|
||||
append_vars(config, [ 'beacon_int', 'beacon_rate', 'rnr_beacon' ]);
|
||||
|
||||
/* wpa_supplicant co-exist */
|
||||
append_vars(config, [ 'noscan' ]);
|
||||
|
||||
/* airtime */
|
||||
if (config.airtime_mode)
|
||||
append_vars(config, [ 'airtime_mode' ]);
|
||||
|
||||
/* assoc/thresholds */
|
||||
append_vars(config, [ 'rssi_reject_assoc_rssi', 'rssi_ignore_probe_request', 'iface_max_num_sta', 'no_probe_resp_if_max_sta' ]);
|
||||
|
||||
/* ACS / Radar*/
|
||||
if (!phy_features.radar_background || config.band != '5g')
|
||||
delete config.enable_background_radar;
|
||||
else
|
||||
set_default(config, 'enable_background_radar', false);
|
||||
|
||||
append_vars(config, [ 'acs_chan_bias', 'acs_exclude_dfs', 'enable_background_radar' ]);
|
||||
|
||||
/* TX Power */
|
||||
append_vars(config, [ 'min_tx_power' ]);
|
||||
|
||||
/* hwmode, channel, op_class, ... */
|
||||
append_vars(config, [ 'hw_mode', 'channel', 'rts_threshold', 'chanlist' ]);
|
||||
if (config.hw_mode in [ 'a', 'g' ] && config.require_mode in [ 'n', 'ac', 'ax' ]) {
|
||||
let require_mode = { n: 'require_ht', ac: 'require_vht', ax: 'require_he' };
|
||||
|
||||
config.legacy_rates = false;
|
||||
append(require_mode[config.require_mode], 1);
|
||||
}
|
||||
device_htmode_append(config);
|
||||
|
||||
if (config.ieee80211ax || config.ieee80211be)
|
||||
append_vars(config, [ 'mbssid' ]);
|
||||
|
||||
/* 6G power mode */
|
||||
if (config.band != '6g')
|
||||
append_vars(config, [ 'reg_power_type' ]);
|
||||
|
||||
/* raw options */
|
||||
for (let raw in config.hostapd_options)
|
||||
append_raw(raw);
|
||||
}
|
||||
|
||||
let iface_idx = 0;
|
||||
function setup_interface(interface, data, config, vlans, stas, phy_features, fixup) {
|
||||
config = { ...config, fixup };
|
||||
|
||||
config.idx = iface_idx++;
|
||||
ap.generate(interface, data, config, vlans, stas, phy_features);
|
||||
}
|
||||
|
||||
export function setup(data) {
|
||||
let file_name = `/var/run/hostapd-${data.phy}${data.vif_phy_suffix}.conf`;
|
||||
|
||||
flush_config();
|
||||
|
||||
if (fs.stat(file_name))
|
||||
fs.rename(file_name, file_name + '.prev');
|
||||
|
||||
data.config.phy = data.phy;
|
||||
|
||||
generate(data.config);
|
||||
|
||||
if (data.config.num_global_macaddr)
|
||||
append('\n#num_global_macaddr', data.config.num_global_macaddr);
|
||||
if (data.config.macaddr_base)
|
||||
append('\n#macaddr_base', data.config.macaddr_base);
|
||||
|
||||
let has_ap;
|
||||
for (let k, interface in data.interfaces) {
|
||||
if (interface.config.mode != 'ap')
|
||||
continue;
|
||||
|
||||
interface.config.network_bridge = interface.bridge;
|
||||
interface.config.network_ifname = interface['bridge-ifname'];
|
||||
|
||||
let owe = interface.config.encryption == 'owe' && interface.config.owe_transition;
|
||||
|
||||
setup_interface(k, data, interface.config, interface.vlans, interface.stas, phy_features, owe ? 'owe' : null );
|
||||
if (owe)
|
||||
setup_interface(k, data, interface.config, interface.vlans, interface.stas, phy_features, 'owe-transition');
|
||||
has_ap = true;
|
||||
}
|
||||
|
||||
let config = dump_config(file_name);
|
||||
|
||||
let msg = {
|
||||
phy: data.phy,
|
||||
radio: data.config.radio,
|
||||
config: has_ap ? file_name : "",
|
||||
prev_config: file_name + '.prev'
|
||||
};
|
||||
let ret = global.ubus.call('hostapd', 'config_set', msg);
|
||||
|
||||
if (ret)
|
||||
netifd.add_process('/usr/sbin/hostapd', ret.pid, true, true);
|
||||
else if (fs.access('/usr/sbin/hostapd', 'x'))
|
||||
netifd.setup_failed('HOSTAPD_START_FAILED');
|
||||
};
|
||||
@@ -1,252 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import { append_value, log } from 'wifi.common';
|
||||
import * as fs from 'fs';
|
||||
|
||||
export function parse_encryption(config, dev_config) {
|
||||
let encryption = split(config.encryption, '+', 2);
|
||||
|
||||
config.wpa = 0;
|
||||
for (let k, v in { 'wpa2*': 2, 'wpa3*': 2, '*psk2*': 2, 'psk3*': 2, 'sae*': 2,
|
||||
'owe*': 2, 'wpa*mixed*': 3, '*psk*mixed*': 3, 'wpa*': 1, '*psk*': 1, })
|
||||
if (wildcard(config.encryption, k)) {
|
||||
config.wpa = v;
|
||||
break;
|
||||
}
|
||||
if (!config.wpa)
|
||||
config.wpa_pairwise = null;
|
||||
|
||||
config.wpa_pairwise = (config.hw_mode == 'ad') ? 'GCMP' : 'CCMP';
|
||||
config.auth_type = encryption[0] ?? 'none';
|
||||
|
||||
let wpa3_pairwise = config.wpa_pairwise;
|
||||
if (wildcard(dev_config?.htmode, 'EHT*') || wildcard(dev_config?.htmode, 'HE*'))
|
||||
wpa3_pairwise = 'GCMP-256 ' + wpa3_pairwise;
|
||||
|
||||
switch(config.auth_type) {
|
||||
case 'owe':
|
||||
config.auth_type = 'owe';
|
||||
break;
|
||||
|
||||
case 'wpa3-192':
|
||||
config.auth_type = 'eap192';
|
||||
break;
|
||||
|
||||
case 'wpa3-mixed':
|
||||
config.auth_type = 'eap-eap2';
|
||||
break;
|
||||
|
||||
case 'wpa3':
|
||||
config.auth_type = 'eap2';
|
||||
break;
|
||||
|
||||
case 'psk':
|
||||
case 'psk-mixed':
|
||||
config.auth_type = "psk";
|
||||
wpa3_pairwise = null;
|
||||
break;
|
||||
|
||||
case 'sae':
|
||||
case 'psk3':
|
||||
config.auth_type = 'sae';
|
||||
break;
|
||||
|
||||
case 'psk3-mixed':
|
||||
case 'sae-mixed':
|
||||
config.auth_type = 'psk-sae';
|
||||
break;
|
||||
|
||||
case 'wpa':
|
||||
case 'wpa2':
|
||||
case 'wpa-mixed':
|
||||
config.auth_type = 'eap';
|
||||
wpa3_pairwise = null;
|
||||
break;
|
||||
|
||||
case 'psk2':
|
||||
wpa3_pairwise = null;
|
||||
break;
|
||||
|
||||
default:
|
||||
config.wpa_pairwise = null;
|
||||
wpa3_pairwise = null;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(encryption[1]){
|
||||
case 'tkip+aes':
|
||||
case 'tkip+ccmp':
|
||||
case 'aes+tkip':
|
||||
case 'ccmp+tkip':
|
||||
config.wpa_pairwise = 'CCMP TKIP';
|
||||
break;
|
||||
|
||||
case 'ccmp256':
|
||||
config.wpa_pairwise = 'CCMP-256';
|
||||
break;
|
||||
|
||||
case 'aes':
|
||||
case 'ccmp':
|
||||
config.wpa_pairwise = 'CCMP';
|
||||
break;
|
||||
|
||||
case 'tkip':
|
||||
config.wpa_pairwise = 'TKIP';
|
||||
break;
|
||||
|
||||
case 'gcmp256':
|
||||
config.wpa_pairwise = 'GCMP-256';
|
||||
break;
|
||||
|
||||
case 'gcmp':
|
||||
config.wpa_pairwise = 'GCMP';
|
||||
break;
|
||||
|
||||
default:
|
||||
if (config.encryption == 'wpa3-192') {
|
||||
config.wpa_pairwise = 'GCMP-256';
|
||||
break;
|
||||
}
|
||||
|
||||
if (!wpa3_pairwise)
|
||||
break;
|
||||
|
||||
if (config.rsn_override)
|
||||
config.rsn_override_pairwise = wpa3_pairwise;
|
||||
else
|
||||
config.wpa_pairwise = wpa3_pairwise;
|
||||
break;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export function wpa_key_mgmt(config) {
|
||||
if (!config.wpa)
|
||||
return;
|
||||
|
||||
switch(config.auth_type) {
|
||||
case 'psk':
|
||||
case 'psk2':
|
||||
append_value(config, 'wpa_key_mgmt', 'WPA-PSK');
|
||||
if (config.wpa >= 2 && config.ieee80211r)
|
||||
append_value(config, 'wpa_key_mgmt', 'FT-PSK');
|
||||
if (config.ieee80211w)
|
||||
append_value(config, 'wpa_key_mgmt', 'WPA-PSK-SHA256');
|
||||
break;
|
||||
|
||||
case 'eap':
|
||||
append_value(config, 'wpa_key_mgmt', 'WPA-EAP');
|
||||
if (config.wpa >= 2 && config.ieee80211r)
|
||||
append_value(config, 'wpa_key_mgmt', 'FT-EAP');
|
||||
if (config.ieee80211w)
|
||||
append_value(config, 'wpa_key_mgmt', 'WPA-EAP-SHA256');
|
||||
break;
|
||||
|
||||
case 'eap192':
|
||||
append_value(config, 'wpa_key_mgmt', 'WPA-EAP-SUITE-B-192');
|
||||
if (config.ieee80211r)
|
||||
append_value(config, 'wpa_key_mgmt', 'FT-EAP-SHA384');
|
||||
break;
|
||||
|
||||
case 'eap-eap2':
|
||||
append_value(config, 'wpa_key_mgmt', 'WPA-EAP-SHA256');
|
||||
if (config.ieee80211r)
|
||||
append_value(config, 'wpa_key_mgmt', 'FT-EAP');
|
||||
|
||||
config.rsn_override_key_mgmt = config.wpa_key_mgmt;
|
||||
append_value(config, 'wpa_key_mgmt', 'WPA-EAP');
|
||||
break;
|
||||
|
||||
case 'eap2':
|
||||
append_value(config, 'wpa_key_mgmt', 'WPA-EAP-SHA256');
|
||||
if (config.ieee80211r)
|
||||
append_value(config, 'wpa_key_mgmt', 'FT-EAP');
|
||||
break;
|
||||
|
||||
case 'sae':
|
||||
append_value(config, 'wpa_key_mgmt', 'SAE');
|
||||
if (config.ieee80211r)
|
||||
append_value(config, 'wpa_key_mgmt', 'FT-SAE');
|
||||
break;
|
||||
|
||||
case 'psk-sae':
|
||||
append_value(config, 'wpa_key_mgmt', 'SAE');
|
||||
if (config.ieee80211r)
|
||||
append_value(config, 'wpa_key_mgmt', 'FT-SAE');
|
||||
config.rsn_override_key_mgmt = config.wpa_key_mgmt;
|
||||
|
||||
append_value(config, 'rsn_override_key_mgmt_2', 'SAE-EXT-KEY');
|
||||
if (config.ieee80211r)
|
||||
append_value(config, 'rsn_override_key_mgmt_2', 'FT-SAE-EXT-KEY');
|
||||
|
||||
if (config.rsn_override > 1)
|
||||
delete config.wpa_key_mgmt;
|
||||
|
||||
append_value(config, 'wpa_key_mgmt', 'WPA-PSK');
|
||||
if (config.ieee80211w)
|
||||
append_value(config, 'wpa_key_mgmt', 'WPA-PSK-SHA256');
|
||||
if (config.ieee80211r)
|
||||
append_value(config, 'wpa_key_mgmt', 'FT-PSK');
|
||||
break;
|
||||
|
||||
case 'owe':
|
||||
append_value(config, 'wpa_key_mgmt', 'OWE');
|
||||
break;
|
||||
}
|
||||
|
||||
if (config.fils) {
|
||||
switch(config.auth_type) {
|
||||
case 'eap192':
|
||||
append_value(config, 'wpa_key_mgmt', 'FILS-SHA384');
|
||||
if (config.ieee80211r)
|
||||
append_value(config, 'wpa_key_mgmt', 'FT-FILS-SHA384');
|
||||
break;
|
||||
|
||||
case 'eap-eap2':
|
||||
case 'eap2':
|
||||
case 'eap':
|
||||
append_value(config, 'wpa_key_mgmt', 'FILS-SHA256');
|
||||
if (config.ieee80211r)
|
||||
append_value(config, 'wpa_key_mgmt', 'FT-FILS-SHA256');
|
||||
|
||||
if (!config.rsn_override_key_mgmt)
|
||||
break;
|
||||
|
||||
append_value(config, 'rsn_override_key_mgmt', 'FILS-SHA256');
|
||||
if (config.ieee80211r)
|
||||
append_value(config, 'rsn_override_key_mgmt', 'FT-FILS-SHA256');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
config.key_mgmt = config.wpa_key_mgmt;
|
||||
};
|
||||
|
||||
function macaddr_random() {
|
||||
let f = fs.open("/dev/urandom", "r");
|
||||
let addr = f.read(6);
|
||||
|
||||
addr = map(split(addr, ""), (v) => ord(v));
|
||||
addr[0] &= ~1;
|
||||
addr[0] |= 2;
|
||||
|
||||
return join(":", map(addr, (v) => sprintf("%02x", v)));
|
||||
}
|
||||
|
||||
let mac_idx = 0;
|
||||
export function prepare(data, phy, num_global_macaddr, macaddr_base) {
|
||||
if (!data.macaddr) {
|
||||
let pipe = fs.popen(`ucode /usr/share/hostap/wdev.uc ${phy} get_macaddr id=${mac_idx} num_global=${num_global_macaddr} mbssid=${data.mbssid ?? 0} macaddr_base=${macaddr_base ?? ""}`);
|
||||
|
||||
data.macaddr = trim(pipe.read("all"), '\n');
|
||||
pipe.close();
|
||||
|
||||
data.default_macaddr = true;
|
||||
mac_idx++;
|
||||
} else if (data.macaddr == 'random') {
|
||||
data.macaddr = macaddr_random();
|
||||
data.random_macaddr = true;
|
||||
}
|
||||
|
||||
log(`Preparing interface: ${data.ifname} with MAC: ${data.macaddr}`);
|
||||
};
|
||||
@@ -1,49 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import { log } from 'wifi.common';
|
||||
import * as fs from 'fs';
|
||||
|
||||
const CMD_UP = 0;
|
||||
const CMD_SET_DATA = 1;
|
||||
const CMD_PROCESS_ADD = 2;
|
||||
const CMD_PROCESS_KILL_ALL = 3;
|
||||
const CMD_SET_RETRY = 4;
|
||||
|
||||
export function notify(command, params, data) {
|
||||
params ??= {};
|
||||
data ??= {};
|
||||
|
||||
global.ubus.call('network.wireless', 'notify', { command, device: global.radio, ...params, data });
|
||||
};
|
||||
|
||||
export function set_up() {
|
||||
notify(CMD_UP);
|
||||
};
|
||||
|
||||
export function set_data(data) {
|
||||
notify(CMD_SET_DATA, null, data);
|
||||
};
|
||||
|
||||
export function add_process(exe, pid, required, keep) {
|
||||
exe = fs.realpath(exe);
|
||||
|
||||
notify(CMD_PROCESS_ADD, null, { pid, exe, required, keep });
|
||||
};
|
||||
|
||||
export function set_retry(retry) {
|
||||
notify(CMD_SET_RETRY, null, { retry });
|
||||
};
|
||||
|
||||
export function set_vif(interface, ifname) {
|
||||
notify(CMD_SET_DATA, { interface }, { ifname });
|
||||
};
|
||||
|
||||
export function set_vlan(interface, ifname, vlan) {
|
||||
notify(CMD_SET_DATA, { interface, vlan }, { ifname });
|
||||
};
|
||||
|
||||
export function setup_failed(reason) {
|
||||
log(`Device setup failed: ${reason}`);
|
||||
printf('%s\n', reason);
|
||||
set_retry(false);
|
||||
};
|
||||
@@ -1,296 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import {
|
||||
append, append_raw, append_vars, network_append, network_append_raw, network_append_vars,
|
||||
network_append_string_vars, set_default, dump_network, flush_network,
|
||||
wiphy_info, wiphy_band
|
||||
} from 'wifi.common';
|
||||
import * as netifd from 'wifi.netifd';
|
||||
import * as iface from 'wifi.iface';
|
||||
import * as fs from 'fs';
|
||||
|
||||
function set_fixed_freq(data, config) {
|
||||
if (!data.frequency)
|
||||
return;
|
||||
|
||||
set_default(config, 'fixed_freq', 1);
|
||||
set_default(config, 'frequency', data.frequency);
|
||||
|
||||
if (data.htmode in [ 'VHT80', 'HE80' ])
|
||||
set_default(config, 'max_oper_chwidth', 1);
|
||||
else if (data.htmode in [ 'VHT160', 'HE160' ])
|
||||
set_default(config, 'max_oper_chwidth', 2);
|
||||
else if (data.htmode in [ 'VHT20', 'VHT40', 'HE20', 'HE40' ])
|
||||
set_default(config, 'max_oper_chwidth', 0);
|
||||
else
|
||||
set_default(config, 'disable_vht', true);
|
||||
|
||||
if (data.htmode in [ 'NOHT' ])
|
||||
set_default(config, 'disable_ht', true);
|
||||
else if (data.htmode in [ 'HT20', 'VHT20', 'HE20' ])
|
||||
set_default(config, 'disable_ht40', true);
|
||||
else if (data.htmode in [ 'VHT40', 'VHT80', 'VHT160', 'HE40', 'HE80', 'HE160' ])
|
||||
set_default(config, 'ht40', true);
|
||||
|
||||
if (wildcard(data.htmode, 'VHT*'))
|
||||
set_default(config, 'vht', 1);
|
||||
}
|
||||
|
||||
export function ratestr(rate) {
|
||||
if (rate == null)
|
||||
return rate;
|
||||
|
||||
let rem = (rate / 100) % 10;
|
||||
rate = int(rate / 1000);
|
||||
if (rem > 0)
|
||||
rate += "." + rem;
|
||||
|
||||
return "" + rate;
|
||||
};
|
||||
|
||||
export function ratelist(rates) {
|
||||
if (length(rates) < 1)
|
||||
return null;
|
||||
|
||||
return join(",", map(rates, (rate) => ratestr(rate)));
|
||||
};
|
||||
|
||||
function setup_sta(data, config) {
|
||||
iface.parse_encryption(config);
|
||||
|
||||
if (config.auth_type in [ 'sae', 'owe', 'eap2', 'eap192' ])
|
||||
config.ieee80211w = 2;
|
||||
else if (config.auth_type in [ 'psk-sae' ])
|
||||
config.ieee80211w = 1;
|
||||
if ((wildcard(data.htmode, 'EHT*') || wildcard(data.htmode, 'HE*')) &&
|
||||
config.rsn_override)
|
||||
config.rsn_overriding = 1;
|
||||
else
|
||||
config.rsn_overriding = 0;
|
||||
|
||||
set_default(config, 'ieee80211r', 0);
|
||||
set_default(config, 'sae_pwe', 2);
|
||||
set_default(config, 'multi_ap', 0);
|
||||
set_default(config, 'multi_profile', 1);
|
||||
set_default(config, 'default_disabled', 0);
|
||||
|
||||
config.scan_ssid = 1;
|
||||
|
||||
switch(config.mode) {
|
||||
case 'sta':
|
||||
set_default(config, 'multi_ap_backhaul_sta', config.multi_ap);
|
||||
break;
|
||||
|
||||
case 'adhoc':
|
||||
config.ap_scan = 2;
|
||||
config.scan_ssid = 0;
|
||||
network_append('mode', 1);
|
||||
set_fixed_freq(data, config);
|
||||
break;
|
||||
|
||||
case 'mesh':
|
||||
config.ssid = config.mesh_id;
|
||||
config.scan_ssid = null;
|
||||
network_append('mode', 5);
|
||||
|
||||
set_fixed_freq(data, config);
|
||||
|
||||
if (config.encryption && config.encryption != 'none')
|
||||
config.key_mgmt = 'SAE';
|
||||
|
||||
config.ieee80211w = null;
|
||||
break;
|
||||
}
|
||||
|
||||
if (config.mode != 'mesh' ) {
|
||||
switch(config.wpa) {
|
||||
case 1:
|
||||
config.proto = 'WPA';
|
||||
break;
|
||||
|
||||
case 2:
|
||||
config.proto = 'RSN';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(config.auth_type) {
|
||||
case 'none':
|
||||
break;
|
||||
|
||||
case 'owe':
|
||||
iface.wpa_key_mgmt(config);
|
||||
break;
|
||||
|
||||
case 'wps':
|
||||
config.key_mgmt = 'WPS';
|
||||
break;
|
||||
|
||||
case 'psk':
|
||||
case 'psk2':
|
||||
case 'sae':
|
||||
case 'psk-sae':
|
||||
if (config.mode != 'mesh')
|
||||
iface.wpa_key_mgmt(config);
|
||||
|
||||
if (config.mode == 'mesh' || config.auth_type == 'sae')
|
||||
config.sae_password = `"${config.key}"`;
|
||||
else
|
||||
config.psk = `"${config.key}"`;
|
||||
|
||||
break;
|
||||
|
||||
case 'eap':
|
||||
case 'eap2':
|
||||
case 'eap192':
|
||||
iface.wpa_key_mgmt(config);
|
||||
set_default(config, 'erp', config.fils);
|
||||
|
||||
if (config.ca_cert_usesystem && fs.stat('/etc/ssl/certs/ca-certificates.crt'))
|
||||
config.ca_cert = '/etc/ssl/certs/ca-certificates.crt';
|
||||
|
||||
switch(config.eap_type) {
|
||||
case 'fast':
|
||||
case 'peap':
|
||||
case 'ttls':
|
||||
set_default(config, 'auth', 'MSCHAPV2');
|
||||
if (config.auth == 'EAP-TLS') {
|
||||
if (config.ca_cert2_usesystem && fs.stat('/etc/ssl/certs/ca-certificates.crt'))
|
||||
config.ca_cert2 = '/etc/ssl/certs/ca-certificates.crt';
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (config.wpa_pairwise == 'GCMP') {
|
||||
config.pairwise = 'GCMP';
|
||||
config.group = 'GCMP';
|
||||
}
|
||||
|
||||
config.key_mgmt ??= 'NONE';
|
||||
|
||||
config.basic_rate = ratelist(config.basic_rate);
|
||||
config.mcast_rate = ratestr(config.mcast_rate);
|
||||
|
||||
network_append_string_vars(config, [ 'ssid' ]);
|
||||
network_append_vars(config, [
|
||||
'rsn_overriding', 'scan_ssid', 'noscan', 'disabled', 'multi_ap_profile', 'multi_ap_backhaul_sta',
|
||||
'ocv', 'key_mgmt', 'sae_pwe', 'psk', 'sae_password', 'pairwise', 'group', 'bssid',
|
||||
'proto', 'mesh_fwding', 'mesh_rssi_threshold', 'frequency', 'fixed_freq',
|
||||
'disable_ht', 'disable_ht40', 'disable_vht', 'vht', 'max_oper_chwidth',
|
||||
'ht40', 'beacon_int', 'ieee80211w', 'basic_rate', 'mcast_rate',
|
||||
'bssid_blacklist', 'bssid_whitelist', 'erp', 'ca_cert', 'identity',
|
||||
'anonymous_identity', 'client_cert', 'private_key', 'private_key_passwd',
|
||||
'subject_match', 'altsubject_match', 'domain_match', 'domain_suffix_match',
|
||||
'ca_cert2', 'client_cert2', 'private_key2', 'private_key2_passwd', 'password'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
function freq_in_range(freq_ranges, freq)
|
||||
{
|
||||
if (!freq_ranges)
|
||||
return true;
|
||||
|
||||
freq *= 1000;
|
||||
for (let range in freq_ranges)
|
||||
if (freq >= range.start && freq <= range.end)
|
||||
return true;
|
||||
}
|
||||
|
||||
function wiphy_frequencies(phy, band, radio) {
|
||||
phy = wiphy_info(phy);
|
||||
band = wiphy_band(phy, band);
|
||||
if (!band)
|
||||
return;
|
||||
|
||||
let ranges;
|
||||
for (let r in phy.radios)
|
||||
if (r.index == radio)
|
||||
ranges = r.freq_ranges;
|
||||
|
||||
let freqs = [];
|
||||
for (let chan in band.freqs)
|
||||
if (!chan.disabled && freq_in_range(ranges, chan.freq))
|
||||
push(freqs, chan.freq);
|
||||
|
||||
if (length(freqs) > 0)
|
||||
return freqs;
|
||||
}
|
||||
|
||||
|
||||
export function generate(config_list, data, interface) {
|
||||
flush_network();
|
||||
|
||||
if (interface.bridge &&
|
||||
(interface.config.mode == 'adhoc' ||
|
||||
(interface.config.mode == 'sta' && !interface.config.wds && !interface.config.multi_ap))){
|
||||
netifd.setup_failed('BRIDGE_NOT_ALLOWED');
|
||||
return 1;
|
||||
}
|
||||
|
||||
interface.config.country = data.config.country_code;
|
||||
interface.config.beacon_int = data.config.beacon_int;
|
||||
if (!data.config.scan_list)
|
||||
data.config.scan_list = wiphy_frequencies(data.phy, data.config.band, data.config.radio);
|
||||
|
||||
if (data.config.scan_list)
|
||||
interface.config.freq_list = join(" ", data.config.scan_list);
|
||||
|
||||
append_vars(interface.config, [ 'country', 'beacon_int', 'freq_list' ]);
|
||||
|
||||
setup_sta(data.config, interface.config);
|
||||
|
||||
let file_name = `/var/run/wpa-supplicant-${interface.config.ifname}.conf`;
|
||||
if (fs.stat(file_name))
|
||||
fs.rename(file_name, file_name + '.prev');
|
||||
dump_network(file_name);
|
||||
|
||||
let config = {
|
||||
mode: interface.config.mode,
|
||||
ctrl: '/var/run/wpa_supplicant',
|
||||
iface: interface.config.ifname,
|
||||
config: file_name,
|
||||
'4addr': !!interface.config.wds,
|
||||
mlo: !!interface.config.mlo,
|
||||
freq_list: data.config.scan_list,
|
||||
powersave: false
|
||||
};
|
||||
|
||||
if (!interface.config.default_macaddr)
|
||||
config.macaddr = interface.config.macaddr;
|
||||
|
||||
if (interface.config.wds)
|
||||
config.bridge = interface.bridge;
|
||||
|
||||
push(config_list, config);
|
||||
|
||||
return config;
|
||||
};
|
||||
|
||||
export function setup(config, data) {
|
||||
let ret = global.ubus.call('wpa_supplicant', 'config_set', {
|
||||
phy: data.phy,
|
||||
radio: data.config.radio,
|
||||
config,
|
||||
defer: true,
|
||||
num_global_macaddr: data.config.num_global_macaddr,
|
||||
macaddr_base: data.config.macaddr_base ?? "",
|
||||
});
|
||||
|
||||
if (ret)
|
||||
netifd.add_process('/usr/sbin/wpa_supplicant', ret.pid, true, true);
|
||||
else if (fs.access('/usr/sbin/wpa_supplicant', 'x'))
|
||||
netifd.setup_failed('SUPPLICANT_START_FAILED');
|
||||
};
|
||||
|
||||
|
||||
export function start(data) {
|
||||
global.ubus.call('wpa_supplicant', 'config_set', {
|
||||
phy: data.phy,
|
||||
radio: data.config.radio,
|
||||
num_global_macaddr: data.config.num_global_macaddr,
|
||||
macaddr_base: data.config.macaddr_base ?? "",
|
||||
});
|
||||
};
|
||||
@@ -1,121 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import { log } from 'wifi.common';
|
||||
import * as fs from 'fs';
|
||||
|
||||
const schemas = {
|
||||
device: json(fs.readfile('/usr/share/schema/wireless.wifi-device.json')).properties,
|
||||
iface: json(fs.readfile('/usr/share/schema/wireless.wifi-iface.json')).properties,
|
||||
vlan: json(fs.readfile('/usr/share/schema/wireless.wifi-vlan.json')).properties,
|
||||
station: json(fs.readfile('/usr/share/schema/wireless.wifi-station.json')).properties,
|
||||
};
|
||||
|
||||
const types = {
|
||||
"array": 1,
|
||||
"string": 3,
|
||||
"number": 5,
|
||||
"boolean": 7,
|
||||
};
|
||||
|
||||
function dump_option(schema, key) {
|
||||
let _key = (schema[key].type == 'alias') ? schema[key].default : key;
|
||||
|
||||
return [
|
||||
key,
|
||||
types[schema[_key].type]
|
||||
];
|
||||
}
|
||||
|
||||
export function dump_options() {
|
||||
let dump = {
|
||||
"name": "mac80211",
|
||||
};
|
||||
|
||||
for (let k, v in schemas) {
|
||||
dump[k] = [];
|
||||
for (let option in v)
|
||||
push(dump[k], dump_option(v, option));
|
||||
};
|
||||
|
||||
printf('%J\n', dump);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
function abort(msg) {
|
||||
log(msg);
|
||||
die();
|
||||
}
|
||||
|
||||
function validate_value(schema, key, value) {
|
||||
switch(schema.type) {
|
||||
case 'number':
|
||||
value = +value;
|
||||
if (schema.minimum && value < schema.minimum)
|
||||
abort(`${key}: ${value} is lower than the minimum value`);
|
||||
if (schema.maximum && value > schema.maximum)
|
||||
abort(`${key}: ${value} is larger than the maximum value`);
|
||||
if (schema.enum && !(value in schema.enum))
|
||||
abort(`${key}: ${value} has to be one of ${schema.enum}`);
|
||||
break;
|
||||
|
||||
case 'boolean':
|
||||
value = !!+value;
|
||||
break;
|
||||
|
||||
case 'string':
|
||||
if (schema.enum && !(value in schema.enum))
|
||||
abort(`${key}: ${value} has to be one of ${schema.enum}`);
|
||||
break;
|
||||
|
||||
case 'array':
|
||||
if (type(value) != 'array')
|
||||
value = [ value ];
|
||||
if (schema.items?.type)
|
||||
for (let k, v in value)
|
||||
value[k] = validate_value(schema.items, key, v);
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
export function validate(schema, dict) {
|
||||
schema = schemas[schema];
|
||||
|
||||
/* complain about anything that is not in the schema */
|
||||
for (let k, v in dict) {
|
||||
if (substr(k, 0, 1) == '.')
|
||||
continue;
|
||||
if (schema[k])
|
||||
continue;
|
||||
log(`${k} is not present in the schema`);
|
||||
}
|
||||
|
||||
/* convert all aliases */
|
||||
for (let k, v in dict) {
|
||||
if (schema[k]?.type != 'alias')
|
||||
continue;
|
||||
if (schema[k].default == null)
|
||||
abort(`${k} alias does not have a default value`);
|
||||
|
||||
dict[schema[k].default] = v;
|
||||
delete dict[k];
|
||||
}
|
||||
|
||||
/* set defaults */
|
||||
for (let k, v in schema) {
|
||||
if (schema[k]?.type == 'alias')
|
||||
continue;
|
||||
if (dict[k] != null || schema[k].default == null)
|
||||
continue;
|
||||
dict[k] = schema[k].default;
|
||||
}
|
||||
|
||||
/* validate value constraints */
|
||||
for (let k, v in dict) {
|
||||
if (!schema[k])
|
||||
continue;
|
||||
dict[k] = validate_value(schema[k], k, v);
|
||||
}
|
||||
};
|
||||
@@ -1,261 +0,0 @@
|
||||
{
|
||||
"pci": [
|
||||
[ "0x0777", "0x11ac", "0x0777", "0xe7f9", 0, 0, "Ubiquiti", "LiteBeam, 5AC" ],
|
||||
[ "0xffff", "0xffff", "0xffff", "0xb102", 0, 0, "Ubiquiti", "PowerStation2, (18V)" ],
|
||||
[ "0xffff", "0xffff", "0xffff", "0xb202", 0, 0, "Ubiquiti", "PowerStation2, (16D)" ],
|
||||
[ "0xffff", "0xffff", "0xffff", "0xb302", 0, 0, "Ubiquiti", "PowerStation2, (EXT)" ],
|
||||
[ "0xffff", "0xffff", "0xffff", "0xb105", 0, 0, "Ubiquiti", "PowerStation5, (22V)" ],
|
||||
[ "0xffff", "0xffff", "0xffff", "0xb305", 0, 0, "Ubiquiti", "PowerStation5, (EXT)" ],
|
||||
[ "0xffff", "0xffff", "0xffff", "0xc302", 0, 0, "Ubiquiti", "PicoStation2" ],
|
||||
[ "0xffff", "0xffff", "0xffff", "0xc3a2", 10, 0, "Ubiquiti", "PicoStation2, HP" ],
|
||||
[ "0xffff", "0xffff", "0xffff", "0xa105", 0, 0, "Ubiquiti", "WispStation5" ],
|
||||
[ "0xffff", "0xffff", "0xffff", "0xa002", 10, 0, "Ubiquiti", "LiteStation2" ],
|
||||
[ "0xffff", "0xffff", "0xffff", "0xa005", 5, 0, "Ubiquiti", "LiteStation5" ],
|
||||
[ "0xffff", "0xffff", "0xffff", "0xc002", 10, 0, "Ubiquiti", "NanoStation2" ],
|
||||
[ "0xffff", "0xffff", "0xffff", "0xc005", 5, 0, "Ubiquiti", "NanoStation5" ],
|
||||
[ "0xffff", "0xffff", "0xffff", "0xc102", 10, 0, "Ubiquiti", "NanoStation, Loco2" ],
|
||||
[ "0xffff", "0xffff", "0xffff", "0xc105", 5, 0, "Ubiquiti", "NanoStation, Loco5" ],
|
||||
[ "0xffff", "0xffff", "0xffff", "0xc202", 10, 0, "Ubiquiti", "Bullet2" ],
|
||||
[ "0xffff", "0xffff", "0xffff", "0xc205", 5, 0, "Ubiquiti", "Bullet5" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe002", 6, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe003", 3, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe005", 5, 0, "Ubiquiti", "NanoStation, M5" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe006", 5, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe009", 6, 0, "Ubiquiti", "NanoStation, Loco, M9" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe012", 10, 0, "Ubiquiti", "NanoStation, M2" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe035", 3, 0, "Ubiquiti", "NanoStation, M3" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe0a2", 2, 0, "Ubiquiti", "NanoStation, Loco, M2" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe0a5", 1, 0, "Ubiquiti", "NanoStation, Loco, M5" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe102", 6, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe105", 5, 0, "Ubiquiti", "Rocket, M5" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe112", 10, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe115", 3, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe1a3", 3, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe1a5", 5, 0, "Ubiquiti", "PowerBridge, M5" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe1b2", 10, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe1b3", 3, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe1b5", 5, 0, "Ubiquiti", "Rocket, M5" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe1b6", 5, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe1b9", 6, 0, "Ubiquiti", "Rocket, M9" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe1c2", 10, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe1c3", 3, 0, "Ubiquiti", "Rocket, M3" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe1c5", 5, 0, "Ubiquiti", "Rocket, M5, GPS" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe1c5", 5, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe1d2", 10, 0, "Ubiquiti", "Rocket, M2, Titanium" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe1d3", 3, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe1d5", 5, 0, "Ubiquiti", "airOS, XM/XW" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe1d9", 6, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe1e3", 3, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe1e5", 5, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe202", 12, 0, "Ubiquiti", "Bullet, M2" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe205", 6, 0, "Ubiquiti", "Bullet, M5" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe212", 1, 0, "Ubiquiti", "AirGrid, M2" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe215", 1, 0, "Ubiquiti", "AirGrid, M5" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe232", 2, 0, "Ubiquiti", "NanoBridge, M2" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe233", 3, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe235", 1, 0, "Ubiquiti", "NanoBridge, M5" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe239", 6, 0, "Ubiquiti", "NanoBridge, M9" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe242", 9, 0, "Ubiquiti", "AirGrid, M2, HP" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe243", 3, 0, "Ubiquiti", "NanoBridge, M3" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe245", 6, 0, "Ubiquiti", "AirGrid, M5, HP" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe252", 9, 0, "Ubiquiti", "AirGrid, M2, HP" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe255", 6, 0, "Ubiquiti", "AirGrid, M5, HP" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe2a3", 3, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe2a5", 5, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe2b2", 10, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe2b5", 1, 0, "Ubiquiti", "NanoBridge, M5" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe2b9", 6, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe2c2", 10, 0, "Ubiquiti", "NanoBeam, M2, Int" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe2c3", 6, 0, "Ubiquiti", "Bullet, M2, XW" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe2c4", 6, 0, "Ubiquiti", "airOS, XW" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe2d2", 12, 0, "Ubiquiti", "Bullet, M2, Titanium, HP" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe2d4", 6, 0, "Ubiquiti", "airOS, XW" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe2d5", 6, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe2e5", 4, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe302", 12, 0, "Ubiquiti", "PicoStation, M2"],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe305", 6, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe345", 6, 0, "Ubiquiti", "WispStation, M5" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe3a5", 5, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe3b5", 6, 0, "Ubiquiti", "airOS, XM/XW" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe3e5", 4, 0, "Ubiquiti", "PowerBeam, M5, 300" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe402", 10, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe405", 1, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe4a2", 1, 0, "Ubiquiti", "AirRouter" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe4a5", 1, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe4b2", 9, 0, "Ubiquiti", "AirRouter, HP" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe4d5", 5, 0, "Ubiquiti", "Rocket, M5, Titanium" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe4e5", 4, 0, "Ubiquiti", "PowerBeam, M5, 400" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe5e5", 4, 0, "Ubiquiti", "airOS, XW" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe6a2", 1, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe6b2", 1, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe6b5", 5, 0, "Ubiquiti", "Rocket, M5, XW" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe6c2", 6, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe6e5", 4, 0, "Ubiquiti", "PowerBeam, M5, 400, ISO" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe7f8", 2, 0, "Ubiquiti", "airOS, XW" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe805", 5, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe812", 6, 0, "Ubiquiti", "NanoBeam, M2, 13" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe815", 4, 0, "Ubiquiti", "NanoBeam, M5, 16" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe825", 4, 0, "Ubiquiti", "NanoBeam, M5, 19" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe835", 6, 0, "Ubiquiti", "AirGrid, M5, XW" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe845", 1, 0, "Ubiquiti", "NanoStation, Loco, M5, XW" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe855", 5, 0, "Ubiquiti", "NanoStation, M5, XW" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe865", 6, 0, "Ubiquiti", "LiteBeam, M5" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe866", 6, 0, "Ubiquiti", "NanoStation, M2, XW" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe867", 2, 0, "Ubiquiti", "NanoStation, Loco, M2, XW" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe868", 7, 0, "Ubiquiti", "Rocket, M2, XW" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe869", 2, 0, "Ubiquiti", "airOS, XW" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe875", 4, 0, "Ubiquiti", "airOS, XW" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe879", 2, 0, "Ubiquiti", "airOS, XW" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe885", 4, 0, "Ubiquiti", "PowerBeam, M5, 620, XW" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe895", 4, 0, "Ubiquiti", "airOS, XW" ],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe8a5", 1, 0, "Ubiquiti", "NanoStation, Loco, M5"],
|
||||
[ "0x168c", "0xffff", "0x0777", "0xe8b5", 5, 0, "Ubiquiti", "airOS, XM" ],
|
||||
[ "0x168c", "0x001b", "0x0777", "0x3002", 10, 0, "Ubiquiti", "XR2" ],
|
||||
[ "0x168c", "0x001b", "0x7777", "0x3002", 10, 0, "Ubiquiti", "XR2" ],
|
||||
[ "0x168c", "0x001b", "0x0777", "0x3b02", 10, 0, "Ubiquiti", "XR2.3" ],
|
||||
[ "0x168c", "0x001b", "0x0777", "0x3c02", 10, 0, "Ubiquiti", "XR2.6" ],
|
||||
[ "0x168c", "0x001b", "0x0777", "0x3b03", 10, 0, "Ubiquiti", "XR3-2.8" ],
|
||||
[ "0x168c", "0x001b", "0x0777", "0x3c03", 10, 0, "Ubiquiti", "XR3-3.6" ],
|
||||
[ "0x168c", "0x001b", "0x0777", "0x3003", 10, 0, "Ubiquiti", "XR3" ],
|
||||
[ "0x168c", "0x001b", "0x0777", "0x3004", 10, 0, "Ubiquiti", "XR4" ],
|
||||
[ "0x168c", "0x001b", "0x0777", "0x3005", 10, 0, "Ubiquiti", "XR5" ],
|
||||
[ "0x168c", "0x001b", "0x7777", "0x3005", 10, 0, "Ubiquiti", "XR5" ],
|
||||
[ "0x168c", "0x001b", "0x0777", "0x3007", 10, 0, "Ubiquiti", "XR7" ],
|
||||
[ "0x168c", "0x001b", "0x0777", "0x3009", 10, -1520, "Ubiquiti", "XR9" ],
|
||||
[ "0x168c", "0x001b", "0x168c", "0x2063", 0, 0, "Atheros", "AR5413" ],
|
||||
[ "0x168c", "0x0013", "0x168c", "0x1042", 1, 0, "Ubiquiti", "SRC" ],
|
||||
[ "0x168c", "0x0013", "0x0777", "0x2041", 10, 0, "Ubiquiti", "SR2" ],
|
||||
[ "0x168c", "0x0013", "0x0777", "0x2004", 6, 0, "Ubiquiti", "SR4" ],
|
||||
[ "0x168c", "0x0013", "0x7777", "0x2004", 6, 0, "Ubiquiti", "SR4" ],
|
||||
[ "0x168c", "0x0013", "0x0777", "0x1004", 6, 0, "Ubiquiti", "SR4C" ],
|
||||
[ "0x168c", "0x0013", "0x7777", "0x1004", 6, 0, "Ubiquiti", "SR4C" ],
|
||||
[ "0x168c", "0x0013", "0x168c", "0x2042", 7, 0, "Ubiquiti", "SR5" ],
|
||||
[ "0x168c", "0x0013", "0x7777", "0x2009", 12, -1500, "Ubiquiti", "SR9" ],
|
||||
[ "0x168c", "0x0027", "0x168c", "0x2082", 7, 0, "Ubiquiti", "SR71A" ],
|
||||
[ "0x168c", "0x0027", "0x0777", "0x4082", 7, 0, "Ubiquiti", "SR71" ],
|
||||
[ "0x168c", "0x0029", "0x0777", "0x4005", 7, 0, "Ubiquiti", "SR71-15" ],
|
||||
[ "0x168c", "0x002a", "0x0777", "0xe302", 12, 0, "Ubiquiti", "PicoStation, M2" ],
|
||||
[ "0x168c", "0x002a", "0x0777", "0xe012", 12, 0, "Ubiquiti", "NanoStation, M2" ],
|
||||
[ "0x168c", "0x002a", "0x0777", "0xe005", 5, 0, "Ubiquiti", "NanoStation, M5" ],
|
||||
[ "0x168c", "0x002a", "0x0777", "0xe202", 12, 0, "Ubiquiti", "Bullet, M2" ],
|
||||
[ "0x168c", "0x002a", "0x0777", "0xe805", 5, 0, "Ubiquiti", "Bullet, M5" ],
|
||||
[ "0x168c", "0x002a", "0x0777", "0xe345", 0, 0, "Ubiquiti", "WispStation, M5" ],
|
||||
[ "0x168c", "0x0029", "0x168c", "0xa094", 0, 0, "Atheros", "AR9220" ],
|
||||
[ "0x168c", "0x0029", "0x168c", "0xa095", 0, 0, "Atheros", "AR9223" ],
|
||||
[ "0x168c", "0x002a", "0x168c", "0xa093", 0, 0, "Atheros", "AR9280" ],
|
||||
[ "0x168c", "0x002b", "0x168c", "0xa091", 0, 0, "Atheros", "AR9285" ],
|
||||
[ "0x168c", "0x002d", "0x168c", "0x209a", 0, 0, "Atheros", "AR9287" ],
|
||||
[ "0x168c", "0x002e", "0x1a3b", "0x1121", 0, 0, "Atheros", "AR9287" ],
|
||||
[ "0x168c", "0x002e", "0x0777", "0xe0a2", 8, 0, "Ubiquiti", "NanoStation, Loco, M2, (XM)" ],
|
||||
[ "0x168c", "0x002e", "0x168c", "0x30a4", 0, 0, "Atheros", "AR9287" ],
|
||||
[ "0x168c", "0x002e", "0x168c", "0xa199", 0, 0, "Atheros", "AR9287" ],
|
||||
[ "0x168c", "0x0030", "0x168c", "0x3112", 0, 0, "Atheros", "AR9380" ],
|
||||
[ "0x168c", "0x0030", "0x168c", "0x3114", 0, 0, "Atheros", "AR9390" ],
|
||||
[ "0x168c", "0x0033", "0x168c", "0xa120", 0, 0, "Atheros", "AR9580" ],
|
||||
[ "0x168c", "0x0033", "0x168c", "0xa136", 0, 0, "Atheros", "AR9580" ],
|
||||
[ "0x168c", "0x0033", "0x168c", "0x3123", 0, 0, "Atheros", "AR9590" ],
|
||||
[ "0x168c", "0x0033", "0x19b6", "0xd014", 0, 0, "MikroTik", "R11e-5HnD" ],
|
||||
[ "0x168c", "0x0033", "0x19b6", "0xd057", 0, 0, "MikroTik", "R11e-5HnDr2" ],
|
||||
[ "0x168c", "0x0033", "0x19b6", "0xd016", 0, 0, "MikroTik", "R11e-2HPnD" ],
|
||||
[ "0x168c", "0x0034", "0x17aa", "0x3214", 0, 0, "Atheros", "AR9462" ],
|
||||
[ "0x168c", "0x003c", "0x0000", "0x0000", 0, 0, "Qualcomm Atheros", "QCA9880" ],
|
||||
[ "0x168c", "0x003c", "0x168c", "0x3223", 0, 0, "Qualcomm Atheros", "QCA9880" ],
|
||||
[ "0x168c", "0x003c", "0x1a56", "0x1420", 0, 0, "Qualcomm Atheros", "QCA9862" ],
|
||||
[ "0x168c", "0x003c", "0x19b6", "0xd03c", 0, 0, "Mikrotik", "R11e-5HacT" ],
|
||||
[ "0x168c", "0x003c", "0x19b6", "0xd075", 0, 0, "Mikrotik", "R11e-5HacD" ],
|
||||
[ "0x168c", "0x003e", "0x168c", "0x3361", 0, 0, "Qualcomm Atheros", "QCA6174" ],
|
||||
[ "0x168c", "0x0046", "0x168c", "0xcafe", 0, 0, "Qualcomm Atheros", "QCA9984" ],
|
||||
[ "0x168c", "0x0040", "0x168c", "0x0002", 0, 0, "Qualcomm Atheros", "QCA9990" ],
|
||||
[ "0x168c", "0x0046", "0x0777", "0xe535", 0, 0, "Qualcomm Atheros", "QCA9994" ],
|
||||
[ "0x168c", "0x0046", "0x0777", "0xe5a2", 0, 0, "Qualcomm Atheros", "QCA9994" ],
|
||||
[ "0x168c", "0x0050", "0x0000", "0x0000", 0, 0, "Qualcomm Atheros", "QCA9887" ],
|
||||
[ "0x168c", "0x0056", "0x0000", "0x0000", 0, 0, "Qualcomm Atheros", "QCA9886" ],
|
||||
[ "0x17cb", "0x1104", "0x17cb", "0x1104", 0, 0, "Qualcomm Atheros", "QCN6024/9024/9074" ],
|
||||
[ "0x1814", "0x3051", "0x1814", "0x0007", 0, 0, "Ralink", "Rt3051" ],
|
||||
[ "0x1814", "0x3052", "0x1814", "0x0008", 0, 0, "Ralink", "Rt3052" ],
|
||||
[ "0x1814", "0x3350", "0x1814", "0x000b", 0, 0, "Ralink", "Rt3350" ],
|
||||
[ "0x1814", "0x3662", "0x1814", "0x000d", 0, 0, "Ralink", "Rt3662" ],
|
||||
[ "0x11ab", "0x2a55", "0x11ab", "0x0000", 0, 0, "Marvell", "88W8864" ],
|
||||
[ "0x02df", "0x9135", "0x0000", "0x0000", 0, 0, "Marvell", "88W8887" ],
|
||||
[ "0x11ab", "0x2b40", "0x11ab", "0x0000", 0, 0, "Marvell", "88W8964" ],
|
||||
[ "0x02df", "0x9141", "0x0000", "0x0000", 0, 0, "Marvell", "88W8997" ],
|
||||
[ "0x14c3", "0x0608", "0x14c3", "0x0608", 0, 0, "AMD", "RZ608" ],
|
||||
[ "0x14c3", "0x7603", "0x14c3", "0x7603", 0, 0, "MediaTek", "MT7603E" ],
|
||||
[ "0x14c3", "0x7610", "0x14c3", "0x7610", 0, 0, "MediaTek", "MT7610E" ],
|
||||
[ "0x14c3", "0x7612", "0x14c3", "0x7612", 0, 0, "MediaTek", "MT7612E" ],
|
||||
[ "0x14c3", "0x7663", "0x14c3", "0x7663", 0, 0, "MediaTek", "MT7613BE" ],
|
||||
[ "0x14c3", "0x7615", "0x7615", "0x14c3", 0, 0, "MediaTek", "MT7615E" ],
|
||||
[ "0x14c3", "0x7628", "0x14c3", "0x0004", 0, 0, "MediaTek", "MT76x8" ],
|
||||
[ "0x14c3", "0x7650", "0x14c3", "0x7650", 0, 0, "MediaTek", "MT7610E" ],
|
||||
[ "0x14c3", "0x7662", "0x14c3", "0x7662", 0, 0, "MediaTek", "MT76x2E" ],
|
||||
[ "0x14c3", "0x7915", "0x14c3", "0x7915", 0, 0, "MediaTek", "MT7915E" ],
|
||||
[ "0x14c3", "0x7906", "0x14c3", "0x7906", 0, 0, "MediaTek", "MT7916AN" ],
|
||||
[ "0x14c3", "0x7990", "0x14C3", "0x6639", 0, 0, "MediaTek", "MT7996E" ],
|
||||
[ "0x14c3", "0x7992", "0x14C3", "0x7992", 0, 0, "MediaTek", "MT7992E" ],
|
||||
[ "0x14e4", "0xaa52", "0x14e4", "0xaa52", 0, 0, "Broadcom", "BCM43602" ],
|
||||
[ "0x02d0", "0xa9a6", "0x0000", "0x0000", 0, 0, "Cypress", "CYW43455" ],
|
||||
[ "0x02d0", "0x4345", "0x0000", "0x0000", 0, 0, "Cypress", "CYW43455" ],
|
||||
[ "0x1ae9", "0x0310", "0x1ae9", "0x0000", 0, 0, "Wilocity", "Wil6210" ],
|
||||
[ "0x0000", "0x0000", "0x148f", "0x7601", 0, 0, "MediaTek", "MT7601U" ],
|
||||
[ "0x0000", "0x0000", "0x0e8d", "0x7961", 0, 0, "MediaTek", "MT7921AU" ],
|
||||
[ "0x0000", "0x0000", "0x0b05", "0x1833", 0, 0, "ASUS", "USB-AC54" ],
|
||||
[ "0x0000", "0x0000", "0x0b05", "0x17eb", 0, 0, "ASUS", "USB-AC55" ],
|
||||
[ "0x0000", "0x0000", "0x0b05", "0x180b", 0, 0, "ASUS", "USB-N53, B1" ],
|
||||
[ "0x0000", "0x0000", "0x0e8d", "0x7612", 0, 0, "Aukey", "USBAC1200" ],
|
||||
[ "0x0000", "0x0000", "0x057c", "0x8503", 0, 0, "AVM", "FRITZ!WLAN, AC860" ],
|
||||
[ "0x0000", "0x0000", "0x7392", "0xb711", 0, 0, "Edimax", "EW-7722UAC" ],
|
||||
[ "0x0000", "0x0000", "0x0e8d", "0x7632", 0, 0, "High, Cloud", "HC-M7662BU1" ],
|
||||
[ "0x0000", "0x0000", "0x2c4e", "0x0103", 0, 0, "Mercury", "UD13" ],
|
||||
[ "0x0000", "0x0000", "0x0846", "0x9053", 0, 0, "Netgear", "A6210" ],
|
||||
[ "0x0000", "0x0000", "0x045e", "0x02e6", 0, 0, "Microsoft", "XBox, One, Wireless, Adapter" ],
|
||||
[ "0x0000", "0x0000", "0x045e", "0x02fe", 0, 0, "Microsoft", "XBox, One, Wireless, Adapter" ],
|
||||
[ "0x0000", "0x0000", "0x148f", "0x7610", 0, 0, "MediaTek", "MT7610U" ],
|
||||
[ "0x0000", "0x0000", "0x13b1", "0x003e", 0, 0, "Linksys", "AE6000" ],
|
||||
[ "0x0000", "0x0000", "0x0e8d", "0x7610", 0, 0, "Sabrent", "NTWLAC" ],
|
||||
[ "0x0000", "0x0000", "0x7392", "0xa711", 0, 0, "Edimax", "7711MAC" ],
|
||||
[ "0x0000", "0x0000", "0x148f", "0x761a", 0, 0, "TP-Link", "TL-WDN5200" ],
|
||||
[ "0x0000", "0x0000", "0x0b05", "0x17d1", 0, 0, "ASUS", "USB-AC51" ],
|
||||
[ "0x0000", "0x0000", "0x0b05", "0x17db", 0, 0, "ASUS", "USB-AC50" ],
|
||||
[ "0x0000", "0x0000", "0x0df6", "0x0075", 0, 0, "Sitecom", "WLA-3100" ],
|
||||
[ "0x0000", "0x0000", "0x2019", "0xab31", 0, 0, "Planex", "GW-450D" ],
|
||||
[ "0x0000", "0x0000", "0x2001", "0x3d02", 0, 0, "D-Link", "DWA-171, rev, B1" ],
|
||||
[ "0x0000", "0x0000", "0x0586", "0x3425", 0, 0, "Zyxel", "NWD6505" ],
|
||||
[ "0x0000", "0x0000", "0x07b8", "0x7610", 0, 0, "AboCom", "AU7212" ],
|
||||
[ "0x0000", "0x0000", "0x04bb", "0x0951", 0, 0, "I-O, DATA", "WN-AC433UK" ],
|
||||
[ "0x0000", "0x0000", "0x057c", "0x8502", 0, 0, "AVM", "FRITZ!WLAN, AC430" ],
|
||||
[ "0x0000", "0x0000", "0x293c", "0x5702", 0, 0, "Comcast", "Xfinity, KXW02AAA" ],
|
||||
[ "0x0000", "0x0000", "0x20f4", "0x806b", 0, 0, "TRENDnet", "TEW-806UBH" ],
|
||||
[ "0x0000", "0x0000", "0x7392", "0xc711", 0, 0, "Devolo", "WiFi, Stick, ac" ],
|
||||
[ "0x0000", "0x0000", "0x0df6", "0x0079", 0, 0, "Sitecom", "WL-356" ],
|
||||
[ "0x0000", "0x0000", "0x2357", "0x0123", 0, 0, "TP-Link", "T2UHP, US, v1" ],
|
||||
[ "0x0000", "0x0000", "0x2357", "0x010b", 0, 0, "TP-Link", "T2UHP, UN, v1" ],
|
||||
[ "0x0000", "0x0000", "0x2357", "0x0105", 0, 0, "TP-Link", "Archer, T1U" ],
|
||||
[ "0x0000", "0x0000", "0x0e8d", "0x7630", 0, 0, "MediaTek", "MT7630U" ],
|
||||
[ "0x0000", "0x0000", "0x0e8d", "0x7650", 0, 0, "MediaTek", "MT7650U" ],
|
||||
[ "0x0000", "0x0000", "0x0e8d", "0x7663", 0, 0, "MediaTek", "MT7663U" ],
|
||||
[ "0x0000", "0x0000", "0x043e", "0x310c", 0, 0, "LG", "LGSBWAC02" ],
|
||||
[ "0x0000", "0x0000", "0x0bda", "0x8176", 0, 0, "Realtek", "RTL8188CU" ],
|
||||
[ "0x0000", "0x0000", "0x0bda", "0xf179", 0, 0, "Realtek", "RTL8188FTV" ]
|
||||
],
|
||||
"compatible": {
|
||||
"qca,ar9130-wifi": [ "Atheros", "AR9130" ],
|
||||
"qca,ar9330-wifi": [ "Atheros", "AR9330" ],
|
||||
"qca,ar9340-wifi": [ "Atheros", "AR9340" ],
|
||||
"qca,qca9530-wifi": [ "Qualcomm Atheros", "QCA9530" ],
|
||||
"qca,qca9550-wifi": [ "Qualcomm Atheros", "QCA9550" ],
|
||||
"qca,qca9560-wifi": [ "Qualcomm Atheros", "QCA9560" ],
|
||||
"qcom,ipq4019-wifi": [ "Qualcomm Atheros", "IPQ4019" ],
|
||||
"qcom,ipq6018-wifi": [ "Qualcomm Atheros", "IPQ6018" ],
|
||||
"qcom,ipq8074-wifi": [ "Qualcomm Atheros", "IPQ8074" ],
|
||||
"mediatek,mt7622-wmac": [ "MediaTek", "MT7622" ],
|
||||
"mediatek,mt7628-wmac": [ "MediaTek", "MT7628" ],
|
||||
"mediatek,mt7981-wmac": [ "MediaTek", "MT7981" ],
|
||||
"mediatek,mt7986-wmac": [ "MediaTek", "MT7986" ],
|
||||
"ralink,rt2880-wmac": [ "Ralink", "Rt2880" ],
|
||||
"ralink,rt3050-wmac": [ "Ralink", "Rt3050" ],
|
||||
"ralink,rt3352-wmac": [ "Ralink", "Rt3352" ],
|
||||
"ralink,rt3883-wmac": [ "Ralink", "Rt3883" ],
|
||||
"ralink,rt5350-wmac": [ "Ralink", "Rt5350" ],
|
||||
"ralink,rt7620-wmac": [ "MediaTek", "MT7620" ]
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ "${ACTION}" = "add" ] && {
|
||||
/sbin/wifi config
|
||||
ubus call network.wireless retry
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Restart ath12k radios that take long time to initialize on boot
|
||||
|
||||
[ "${ACTION}" = "add" ] || exit 0
|
||||
[ $(grep -c DRIVER=ath12k_pci /sys/$DEVPATH/device/uevent) -gt 0 ] || exit 0
|
||||
|
||||
. /usr/share/libubox/jshn.sh
|
||||
|
||||
restart_radio() {
|
||||
radio=$1
|
||||
arg="{\"radio\": \"$radio\"}"
|
||||
ubus call network reload
|
||||
ubus call network.wireless down "$arg"
|
||||
ubus call network.wireless up "$arg"
|
||||
}
|
||||
|
||||
json_init
|
||||
json_load "$(ubus -S call network.wireless status)"
|
||||
json_get_keys radios
|
||||
for radio in $radios; do
|
||||
json_select $radio
|
||||
json_get_vars up
|
||||
json_get_vars retry_setup_failed
|
||||
|
||||
json_select config
|
||||
json_get_vars path
|
||||
json_select ..
|
||||
|
||||
if [ $up = 0 -a $retry_setup_failed = 1 ] &&
|
||||
[ $(iwinfo nl80211 phyname "path=$path") = "$DEVICENAME" ]; then
|
||||
restart_radio $radio
|
||||
fi
|
||||
|
||||
json_select ..
|
||||
done
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/bin/sh
|
||||
[ "$ACTION" = "pressed" ] && exit 5
|
||||
for script in /etc/rc.wps/*; do
|
||||
[ -x "$script" ] || continue
|
||||
"$script" && break
|
||||
done
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ "$SEEN" -ge 3 ] && exit 1
|
||||
wps_done=0
|
||||
ubusobjs="$( ubus -S list hostapd.* )"
|
||||
for ubusobj in $ubusobjs; do
|
||||
ubus -S call $ubusobj wps_start && wps_done=1
|
||||
done
|
||||
[ $wps_done = 1 ]
|
||||
|
||||
@@ -1,451 +0,0 @@
|
||||
NETIFD_MAIN_DIR="${NETIFD_MAIN_DIR:-/lib/netifd}"
|
||||
|
||||
. /usr/share/libubox/jshn.sh
|
||||
. $NETIFD_MAIN_DIR/utils.sh
|
||||
|
||||
CMD_UP=0
|
||||
CMD_SET_DATA=1
|
||||
CMD_PROCESS_ADD=2
|
||||
CMD_PROCESS_KILL_ALL=3
|
||||
CMD_SET_RETRY=4
|
||||
|
||||
add_driver() {
|
||||
return
|
||||
}
|
||||
|
||||
wireless_setup_vif_failed() {
|
||||
local error="$1"
|
||||
echo "Interface $_w_iface setup failed: $error"
|
||||
}
|
||||
|
||||
wireless_setup_failed() {
|
||||
local error="$1"
|
||||
|
||||
echo "Device setup failed: $error"
|
||||
wireless_set_retry 0
|
||||
}
|
||||
|
||||
prepare_key_wep() {
|
||||
local key="$1"
|
||||
local hex=1
|
||||
|
||||
echo -n "$key" | grep -qE "[^a-fA-F0-9]" && hex=0
|
||||
[ "${#key}" -eq 10 -a $hex -eq 1 ] || \
|
||||
[ "${#key}" -eq 26 -a $hex -eq 1 ] || {
|
||||
[ "${key:0:2}" = "s:" ] && key="${key#s:}"
|
||||
key="$(echo -n "$key" | hexdump -ve '1/1 "%02x" ""')"
|
||||
}
|
||||
echo "$key"
|
||||
}
|
||||
|
||||
_wdev_prepare_channel() {
|
||||
json_get_vars channel band hwmode htmode
|
||||
|
||||
auto_channel=0
|
||||
enable_ht=0
|
||||
hwmode="${hwmode##11}"
|
||||
|
||||
case "$channel" in
|
||||
""|0|auto)
|
||||
channel=0
|
||||
auto_channel=1
|
||||
;;
|
||||
[0-9]*) ;;
|
||||
*)
|
||||
wireless_setup_failed "INVALID_CHANNEL"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$hwmode" in
|
||||
a|b|g|ad) ;;
|
||||
*)
|
||||
if [ "$channel" -gt 14 ]; then
|
||||
hwmode=a
|
||||
else
|
||||
hwmode=g
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$band" in
|
||||
2g) hwmode=g;;
|
||||
5g|6g) hwmode=a;;
|
||||
60g) hwmode=ad;;
|
||||
*)
|
||||
case "$hwmode" in
|
||||
*a) band=5g;;
|
||||
*ad) band=60g;;
|
||||
*b|*g) band=2g;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$htmode" in
|
||||
HE*|EHT*) wpa3_cipher="GCMP-256 ";;
|
||||
*) wpa3_cipher="";;
|
||||
esac
|
||||
}
|
||||
|
||||
_wdev_handler() {
|
||||
json_load "$data"
|
||||
|
||||
json_select config
|
||||
_wdev_prepare_channel
|
||||
json_select ..
|
||||
|
||||
eval "drv_$1_$2 \"$interface\""
|
||||
}
|
||||
|
||||
_wdev_msg_call() {
|
||||
local old_cb
|
||||
|
||||
json_set_namespace wdev old_cb
|
||||
"$@"
|
||||
json_set_namespace $old_cb
|
||||
}
|
||||
|
||||
_wdev_wrapper() {
|
||||
while [ -n "$1" ]; do
|
||||
eval "$1() { _wdev_msg_call _$1 \"\$@\"; }"
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
_wdev_notify_init() {
|
||||
local command="$1"; shift;
|
||||
|
||||
json_init
|
||||
json_add_int "command" "$command"
|
||||
json_add_string "device" "$__netifd_device"
|
||||
while [ -n "$1" ]; do
|
||||
local name="$1"; shift
|
||||
local value="$1"; shift
|
||||
json_add_string "$name" "$value"
|
||||
done
|
||||
json_add_object "data"
|
||||
}
|
||||
|
||||
_wdev_notify() {
|
||||
local options="$1"
|
||||
|
||||
json_close_object
|
||||
ubus $options call network.wireless notify "$(json_dump)"
|
||||
}
|
||||
|
||||
_wdev_add_variables() {
|
||||
while [ -n "$1" ]; do
|
||||
local var="${1%%=*}"
|
||||
local val="$1"
|
||||
shift
|
||||
[[ "$var" = "$val" ]] && continue
|
||||
val="${val#*=}"
|
||||
json_add_string "$var" "$val"
|
||||
done
|
||||
}
|
||||
|
||||
_wireless_add_vif() {
|
||||
local name="$1"; shift
|
||||
local ifname="$1"; shift
|
||||
|
||||
_wdev_notify_init $CMD_SET_DATA "interface" "$name"
|
||||
json_add_string "ifname" "$ifname"
|
||||
_wdev_add_variables "$@"
|
||||
_wdev_notify
|
||||
}
|
||||
|
||||
_wireless_add_vlan() {
|
||||
local name="$1"; shift
|
||||
local ifname="$1"; shift
|
||||
|
||||
_wdev_notify_init $CMD_SET_DATA interface "$__cur_interface" "vlan" "$name"
|
||||
json_add_string "ifname" "$ifname"
|
||||
_wdev_add_variables "$@"
|
||||
_wdev_notify
|
||||
}
|
||||
|
||||
_wireless_set_up() {
|
||||
_wdev_notify_init $CMD_UP
|
||||
_wdev_notify
|
||||
}
|
||||
|
||||
_wireless_set_data() {
|
||||
_wdev_notify_init $CMD_SET_DATA
|
||||
_wdev_add_variables "$@"
|
||||
_wdev_notify
|
||||
}
|
||||
|
||||
_wireless_add_process() {
|
||||
_wdev_notify_init $CMD_PROCESS_ADD
|
||||
local exe="$2"
|
||||
[ -L "$exe" ] && exe="$(readlink -f "$exe")"
|
||||
json_add_int pid "$1"
|
||||
json_add_string exe "$exe"
|
||||
[ -n "$3" ] && json_add_boolean required 1
|
||||
[ -n "$4" ] && json_add_boolean keep 1
|
||||
exe2="$(readlink -f /proc/$1/exe)"
|
||||
[ "$exe" != "$exe2" ] && echo "WARNING (wireless_add_process): executable path $exe does not match process $1 path ($exe2)"
|
||||
_wdev_notify
|
||||
}
|
||||
|
||||
_wireless_process_kill_all() {
|
||||
_wdev_notify_init $CMD_PROCESS_KILL_ALL
|
||||
[ -n "$1" ] && json_add_int signal "$1"
|
||||
_wdev_notify
|
||||
}
|
||||
|
||||
_wireless_set_retry() {
|
||||
_wdev_notify_init $CMD_SET_RETRY
|
||||
json_add_int retry "$1"
|
||||
_wdev_notify
|
||||
}
|
||||
|
||||
_wdev_wrapper \
|
||||
wireless_add_vif \
|
||||
wireless_add_vlan \
|
||||
wireless_set_up \
|
||||
wireless_set_data \
|
||||
wireless_add_process \
|
||||
wireless_process_kill_all \
|
||||
wireless_set_retry \
|
||||
|
||||
wireless_vif_parse_encryption() {
|
||||
json_get_vars encryption rsn_override
|
||||
set_default encryption none
|
||||
|
||||
set_default rsn_override 1
|
||||
auth_mode_open=1
|
||||
auth_mode_shared=0
|
||||
auth_type=none
|
||||
wpa_override_cipher=
|
||||
rsn_override_pairwise=
|
||||
|
||||
if [ "$hwmode" = "ad" ]; then
|
||||
wpa_cipher="GCMP"
|
||||
else
|
||||
wpa_cipher="CCMP"
|
||||
case "$encryption" in
|
||||
sae*|wpa3*|psk3*|owe)
|
||||
if [ "$rsn_override" -gt 0 ]; then
|
||||
wpa_override_cipher="${wpa3_cipher}$wpa_cipher"
|
||||
else
|
||||
wpa_cipher="${wpa3_cipher}$wpa_cipher"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
case "$encryption" in
|
||||
*tkip+aes|*tkip+ccmp|*aes+tkip|*ccmp+tkip) wpa_cipher="CCMP TKIP";;
|
||||
*ccmp256) wpa_cipher="CCMP-256";;
|
||||
*aes|*ccmp) wpa_cipher="CCMP";;
|
||||
*tkip) wpa_cipher="TKIP";;
|
||||
*gcmp256) wpa_cipher="GCMP-256";;
|
||||
*gcmp) wpa_cipher="GCMP";;
|
||||
wpa3-192*) wpa_cipher="GCMP-256";;
|
||||
*) rsn_override_pairwise="$wpa_override_cipher";;
|
||||
esac
|
||||
|
||||
# 802.11n requires CCMP for WPA
|
||||
[ "$enable_ht:$wpa_cipher" = "1:TKIP" ] && wpa_cipher="CCMP TKIP"
|
||||
|
||||
# Examples:
|
||||
# psk-mixed/tkip => WPA1+2 PSK, TKIP
|
||||
# wpa-psk2/tkip+aes => WPA2 PSK, CCMP+TKIP
|
||||
# wpa2/tkip+aes => WPA2 RADIUS, CCMP+TKIP
|
||||
|
||||
case "$encryption" in
|
||||
wpa2*|wpa3*|*psk2*|psk3*|sae*|owe*)
|
||||
wpa=2
|
||||
;;
|
||||
wpa*mixed*|*psk*mixed*)
|
||||
wpa=3
|
||||
;;
|
||||
wpa*|*psk*)
|
||||
wpa=1
|
||||
;;
|
||||
*)
|
||||
wpa=0
|
||||
wpa_cipher=
|
||||
;;
|
||||
esac
|
||||
wpa_pairwise="$wpa_cipher"
|
||||
|
||||
case "$encryption" in
|
||||
owe*)
|
||||
auth_type=owe
|
||||
;;
|
||||
wpa3-192*)
|
||||
auth_type=eap192
|
||||
;;
|
||||
wpa3-mixed*)
|
||||
auth_type=eap-eap2
|
||||
;;
|
||||
wpa3*)
|
||||
auth_type=eap2
|
||||
;;
|
||||
psk3-mixed*|sae-mixed*)
|
||||
auth_type=psk-sae
|
||||
;;
|
||||
psk3*|sae*)
|
||||
auth_type=sae
|
||||
;;
|
||||
*psk*)
|
||||
auth_type=psk
|
||||
;;
|
||||
*wpa*|*8021x*)
|
||||
auth_type=eap
|
||||
;;
|
||||
*wep*)
|
||||
auth_type=wep
|
||||
case "$encryption" in
|
||||
*shared*)
|
||||
auth_mode_open=0
|
||||
auth_mode_shared=1
|
||||
;;
|
||||
*mixed*)
|
||||
auth_mode_shared=1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
_wireless_set_brsnoop_isolation() {
|
||||
local multicast_to_unicast="$1"
|
||||
local isolate
|
||||
|
||||
json_get_vars isolate proxy_arp
|
||||
|
||||
[ ${isolate:-0} -gt 0 -o -z "$network_bridge" ] && return
|
||||
[ ${multicast_to_unicast:-1} -gt 0 -o ${proxy_arp:-0} -gt 0 ] && json_add_boolean isolate 1
|
||||
}
|
||||
|
||||
for_each_interface() {
|
||||
local _w_types="$1"; shift
|
||||
local _w_ifaces _w_iface
|
||||
local _w_type
|
||||
local _w_found
|
||||
|
||||
local multicast_to_unicast
|
||||
|
||||
json_get_keys _w_ifaces interfaces
|
||||
json_select interfaces
|
||||
for _w_iface in $_w_ifaces; do
|
||||
json_select "$_w_iface"
|
||||
if [ -n "$_w_types" ]; then
|
||||
json_get_var network_bridge bridge
|
||||
json_get_var network_ifname bridge-ifname
|
||||
json_get_var multicast_to_unicast multicast_to_unicast
|
||||
json_select config
|
||||
_wireless_set_brsnoop_isolation "$multicast_to_unicast"
|
||||
json_get_var _w_type mode
|
||||
json_select ..
|
||||
_w_types=" $_w_types "
|
||||
[[ "${_w_types%$_w_type*}" = "$_w_types" ]] && {
|
||||
json_select ..
|
||||
continue
|
||||
}
|
||||
fi
|
||||
__cur_interface="$_w_iface"
|
||||
"$@" "$_w_iface"
|
||||
json_select ..
|
||||
done
|
||||
json_select ..
|
||||
}
|
||||
|
||||
for_each_vlan() {
|
||||
local _w_vlans _w_vlan
|
||||
|
||||
json_get_keys _w_vlans vlans
|
||||
json_select vlans
|
||||
for _w_vlan in $_w_vlans; do
|
||||
json_select "$_w_vlan"
|
||||
json_select config
|
||||
"$@" "$_w_vlan"
|
||||
json_select ..
|
||||
json_select ..
|
||||
done
|
||||
json_select ..
|
||||
}
|
||||
|
||||
for_each_station() {
|
||||
local _w_stas _w_sta
|
||||
|
||||
json_get_keys _w_stas stas
|
||||
json_select stas
|
||||
for _w_sta in $_w_stas; do
|
||||
json_select "$_w_sta"
|
||||
json_select config
|
||||
"$@" "$_w_sta"
|
||||
json_select ..
|
||||
json_select ..
|
||||
done
|
||||
json_select ..
|
||||
}
|
||||
|
||||
_wdev_common_device_config() {
|
||||
config_add_string channel hwmode band htmode noscan
|
||||
}
|
||||
|
||||
_wdev_common_iface_config() {
|
||||
config_add_string mode ssid encryption 'key:wpakey'
|
||||
config_add_boolean bridge_isolate
|
||||
config_add_array tags
|
||||
}
|
||||
|
||||
_wdev_common_vlan_config() {
|
||||
config_add_string name vid iface
|
||||
config_add_boolean bridge_isolate
|
||||
}
|
||||
|
||||
_wdev_common_station_config() {
|
||||
config_add_string mac key vid iface
|
||||
}
|
||||
|
||||
init_wireless_driver() {
|
||||
name="$1"; shift
|
||||
cmd="$1"; shift
|
||||
|
||||
case "$cmd" in
|
||||
dump)
|
||||
add_driver() {
|
||||
eval "drv_$1_cleanup"
|
||||
|
||||
json_init
|
||||
json_add_string name "$1"
|
||||
|
||||
json_add_array device
|
||||
_wdev_common_device_config
|
||||
eval "drv_$1_init_device_config"
|
||||
json_close_array
|
||||
|
||||
json_add_array iface
|
||||
_wdev_common_iface_config
|
||||
eval "drv_$1_init_iface_config"
|
||||
json_close_array
|
||||
|
||||
json_add_array vlan
|
||||
_wdev_common_vlan_config
|
||||
eval "drv_$1_init_vlan_config"
|
||||
json_close_array
|
||||
|
||||
json_add_array station
|
||||
_wdev_common_station_config
|
||||
eval "drv_$1_init_station_config"
|
||||
json_close_array
|
||||
|
||||
json_dump
|
||||
}
|
||||
;;
|
||||
setup|teardown)
|
||||
interface="$1"; shift
|
||||
data="$1"; shift
|
||||
export __netifd_device="$interface"
|
||||
|
||||
add_driver() {
|
||||
[[ "$name" == "$1" ]] || return 0
|
||||
_wdev_handler "$1" "$cmd"
|
||||
}
|
||||
;;
|
||||
esac
|
||||
}
|
||||
@@ -1,649 +0,0 @@
|
||||
'use strict';
|
||||
import * as ubus from "ubus";
|
||||
import * as uloop from "uloop";
|
||||
import { is_equal } from "./utils.uc";
|
||||
import { access } from "fs";
|
||||
|
||||
const NOTIFY_CMD_UP = 0;
|
||||
const NOTIFY_CMD_SET_DATA = 1;
|
||||
const NOTIFY_CMD_PROCESS_ADD = 2;
|
||||
const NOTIFY_CMD_SET_RETRY = 4;
|
||||
|
||||
const DEFAULT_RETRY = 3;
|
||||
const DEFAULT_SCRIPT_TIMEOUT = 30 * 1000;
|
||||
|
||||
let wdev_cur;
|
||||
let wdev_handler = {};
|
||||
let wdev_script_task, wdev_script_timeout;
|
||||
let handler_timer;
|
||||
|
||||
function wireless_config_done()
|
||||
{
|
||||
ubus.call({
|
||||
object: "wpa_supplicant",
|
||||
method: "mld_start",
|
||||
return: "ignore",
|
||||
data: { },
|
||||
});
|
||||
|
||||
ubus.call({
|
||||
object: "service",
|
||||
method: "event",
|
||||
return: "ignore",
|
||||
data: {
|
||||
type: "netifd.wireless.done",
|
||||
data: {},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function delete_wdev(name)
|
||||
{
|
||||
delete netifd.wireless.devices[name];
|
||||
gc();
|
||||
}
|
||||
|
||||
function handle_link(dev, data, up)
|
||||
{
|
||||
let config = data.config;
|
||||
let bridge_isolate;
|
||||
let ap = false;
|
||||
if (dev == data.ifname)
|
||||
ap = data.type == "vlan" ||
|
||||
(data.type == "vif" && config.mode == "ap");
|
||||
|
||||
let dev_data = {
|
||||
external: 2,
|
||||
check_vlan: false,
|
||||
isolate: !!config.bridge_isolate,
|
||||
wireless: true,
|
||||
wireless_ap: ap,
|
||||
};
|
||||
|
||||
if (ap && config.multicast_to_unicast != null)
|
||||
dev_data.multicast_to_unicast = config.multicast_to_unicast;
|
||||
|
||||
if (data.type == "vif" && config.mode == "ap") {
|
||||
dev_data.wireless_proxyarp = !!config.proxy_arp;
|
||||
dev_data.wireless_isolate = !!config.isolate;
|
||||
}
|
||||
|
||||
if (up)
|
||||
netifd.device_set(dev, dev_data);
|
||||
|
||||
for (let net in config.network)
|
||||
netifd.interface_handle_link({
|
||||
name: net,
|
||||
ifname: dev,
|
||||
vlan: config.network_vlan,
|
||||
link_ext: true,
|
||||
up,
|
||||
});
|
||||
}
|
||||
|
||||
function wdev_config_init(wdev)
|
||||
{
|
||||
let data = wdev.data;
|
||||
let config = data.config;
|
||||
let interfaces = {};
|
||||
|
||||
let vif_idx = 0;
|
||||
for (let vif in data.vif) {
|
||||
let vlan_idx = 0, sta_idx = 0;
|
||||
let vlans = {}, stas = {};
|
||||
|
||||
if (wdev.disabled_vifs[vif.name])
|
||||
continue;
|
||||
for (let vlan in vif.vlan) {
|
||||
let vlan_name = sprintf("%02d", ++vlan_idx);
|
||||
let cur_vlan = vlans[vlan_name] = {
|
||||
name: vlan.name,
|
||||
config: vlan.config,
|
||||
};
|
||||
|
||||
if (wdev.disabled_vifs[vif.name])
|
||||
continue;
|
||||
for (let net in vlan.config.network)
|
||||
if (netifd.interface_get_bridge(net, cur_vlan))
|
||||
break;
|
||||
}
|
||||
|
||||
for (let sta in vif.sta) {
|
||||
let sta_name = sprintf("%02d", ++sta_idx);
|
||||
stas[sta_name] = {
|
||||
name: sta.name,
|
||||
config: sta.config,
|
||||
};
|
||||
}
|
||||
|
||||
let vif_name = sprintf("%02d", ++vif_idx);
|
||||
let iface = interfaces[vif_name] = {
|
||||
name: vif.name,
|
||||
config: vif.config,
|
||||
vlans, stas,
|
||||
};
|
||||
|
||||
for (let net in vif.config.network)
|
||||
if (netifd.interface_get_bridge(net, iface))
|
||||
break;
|
||||
}
|
||||
|
||||
wdev.handler_config = {
|
||||
config,
|
||||
interfaces,
|
||||
};
|
||||
|
||||
let prev = wdev.handler_data;
|
||||
wdev.handler_data = {};
|
||||
|
||||
if (prev && prev[wdev.name])
|
||||
wdev.handler_data[wdev.name] = prev[wdev.name];
|
||||
}
|
||||
|
||||
function wdev_setup_cb(wdev)
|
||||
{
|
||||
if (wdev.state != "setup")
|
||||
return;
|
||||
|
||||
if (wdev.retry > 0)
|
||||
wdev.retry--;
|
||||
else
|
||||
wdev.retry_setup_failed = true;
|
||||
|
||||
wdev.teardown();
|
||||
}
|
||||
|
||||
function wdev_teardown_cb(wdev)
|
||||
{
|
||||
for (let section, data in wdev.handler_data) {
|
||||
if (data.ifname)
|
||||
handle_link(data.ifname, data, false);
|
||||
}
|
||||
|
||||
wdev.handler_data = {};
|
||||
wdev.state = "down";
|
||||
|
||||
if (wdev.delete) {
|
||||
delete_wdev(wdev.data.name);
|
||||
return;
|
||||
}
|
||||
|
||||
wdev.setup();
|
||||
}
|
||||
|
||||
function run_handler_cb(wdev, cb)
|
||||
{
|
||||
if (wdev != wdev_cur.wdev)
|
||||
return;
|
||||
|
||||
wdev.dbg("complete " + wdev_cur.op);
|
||||
if (wdev_script_timeout)
|
||||
wdev_script_timeout.cancel();
|
||||
wdev_script_timeout = null;
|
||||
wdev_script_task = null;
|
||||
wdev_cur = null;
|
||||
handler_timer.set(1);
|
||||
cb(wdev);
|
||||
}
|
||||
|
||||
function run_handler_timeout(wdev, cb)
|
||||
{
|
||||
wdev_script_task.cancel();
|
||||
run_handler_cb(wdev, cb);
|
||||
}
|
||||
|
||||
function handler_sort_fn(a, b)
|
||||
{
|
||||
return wdev_handler[a].time - wdev_handler[b].time
|
||||
}
|
||||
|
||||
function __run_next_handler_name()
|
||||
{
|
||||
return sort(keys(wdev_handler), handler_sort_fn)[0];
|
||||
}
|
||||
|
||||
function __run_next_handler()
|
||||
{
|
||||
let name = __run_next_handler_name();
|
||||
if (!name)
|
||||
return;
|
||||
|
||||
wdev_cur = wdev_handler[name];
|
||||
delete wdev_handler[name];
|
||||
|
||||
let wdev = wdev_cur.wdev;
|
||||
let op = wdev_cur.op;
|
||||
let cb = wdev_cur.cb;
|
||||
|
||||
wdev.dbg("run " + op);
|
||||
wdev.handler_config.data = wdev.handler_data[wdev.name] ?? {};
|
||||
wdev_script_task = netifd.process({
|
||||
cb: () => run_handler_cb(wdev, cb),
|
||||
dir: netifd.wireless.path,
|
||||
argv: [ './' + wdev.script, wdev.data.config.type, op, wdev.name, "" + wdev.handler_config ],
|
||||
log_prefix: wdev.name,
|
||||
});
|
||||
|
||||
if (!wdev_script_task)
|
||||
return run_handler_cb(wdev, cb);
|
||||
|
||||
wdev_script_timeout = uloop.timer(DEFAULT_SCRIPT_TIMEOUT,
|
||||
() => run_handler_timeout(wdev, cb)
|
||||
);
|
||||
}
|
||||
|
||||
function run_next_handler()
|
||||
{
|
||||
while (!wdev_cur && length(wdev_handler) > 0)
|
||||
__run_next_handler();
|
||||
|
||||
if (!wdev_cur && !length(wdev_handler))
|
||||
wireless_config_done();
|
||||
}
|
||||
|
||||
function run_handler(wdev, op, cb)
|
||||
{
|
||||
wdev.dbg("queue " + op);
|
||||
wdev_handler[wdev.name] = {
|
||||
op, wdev, cb,
|
||||
time: time()
|
||||
};
|
||||
|
||||
run_next_handler();
|
||||
}
|
||||
|
||||
function wdev_proc_reset(wdev)
|
||||
{
|
||||
if (wdev.proc_timer) {
|
||||
wdev.proc_timer.cancel();
|
||||
delete wdev.proc_timer;
|
||||
}
|
||||
|
||||
wdev.procs = [];
|
||||
}
|
||||
|
||||
function __wdev_proc_check(wdev, proc)
|
||||
{
|
||||
if (netifd.process_check(proc.pid, proc.exe))
|
||||
return;
|
||||
|
||||
wdev.dbg(`process ${proc.exe}(${proc.pid}) no longer active`);
|
||||
wdev.teardown();
|
||||
return true;
|
||||
}
|
||||
|
||||
function wdev_proc_check(wdev)
|
||||
{
|
||||
for (let proc in wdev.procs)
|
||||
if (__wdev_proc_check(wdev, proc))
|
||||
break;
|
||||
}
|
||||
|
||||
function wdev_proc_add(wdev, data)
|
||||
{
|
||||
if (!data.pid || !data.exe)
|
||||
return;
|
||||
|
||||
push(wdev.procs, data);
|
||||
|
||||
if (!wdev.proc_timer)
|
||||
wdev.proc_timer = uloop.interval(1000, () => wdev_proc_check(wdev));
|
||||
}
|
||||
|
||||
|
||||
function setup()
|
||||
{
|
||||
if (this.state != "up" && this.state != "down")
|
||||
return;
|
||||
|
||||
this.dbg("setup, state=" + this.state);
|
||||
if (!this.autostart || this.retry_setup_failed)
|
||||
return;
|
||||
|
||||
wdev_proc_reset(this);
|
||||
delete this.config_change;
|
||||
this.state = "setup";
|
||||
run_handler(this, "setup", wdev_setup_cb);
|
||||
}
|
||||
|
||||
function teardown()
|
||||
{
|
||||
delete this.cancel_setup;
|
||||
|
||||
this.dbg("teardown, state=" + this.state);
|
||||
if (this.state == "teardown" || this.state == "down")
|
||||
return;
|
||||
|
||||
wdev_proc_reset(this);
|
||||
this.state = "teardown";
|
||||
run_handler(this, "teardown", wdev_teardown_cb);
|
||||
}
|
||||
|
||||
function wdev_update_disabled_vifs(wdev)
|
||||
{
|
||||
let cache = wdev.ifindex_cache;
|
||||
let prev_disabled = wdev.disabled_vifs;
|
||||
let disabled = wdev.disabled_vifs = {};
|
||||
let changed;
|
||||
|
||||
let vifs = [];
|
||||
for (let vif in wdev.data.vif)
|
||||
push(vifs, vif, ...vif.vlan);
|
||||
|
||||
for (let vif in vifs) {
|
||||
let enabled, ifindex;
|
||||
|
||||
for (let net in vif.config.network) {
|
||||
let state = netifd.interface_get_enabled(net);
|
||||
if (!state)
|
||||
continue;
|
||||
|
||||
if (state.enabled)
|
||||
enabled = true;
|
||||
else if (enabled == null)
|
||||
enabled = false;
|
||||
if (state.ifindex)
|
||||
ifindex = state.ifindex;
|
||||
}
|
||||
|
||||
let name = vif.name;
|
||||
if (enabled == false)
|
||||
disabled[wdev] = true;
|
||||
else if (ifindex != cache[name])
|
||||
changed = true;
|
||||
|
||||
if (ifindex)
|
||||
cache[name] = ifindex;
|
||||
else
|
||||
delete cache[name];
|
||||
}
|
||||
|
||||
if (changed || !is_equal(prev_disabled, disabled))
|
||||
wdev.config_change = true;
|
||||
|
||||
return wdev.config_change;
|
||||
}
|
||||
|
||||
function wdev_reset(wdev)
|
||||
{
|
||||
wdev.retry = DEFAULT_RETRY;
|
||||
delete wdev.retry_setup_failed;
|
||||
}
|
||||
|
||||
function update(data)
|
||||
{
|
||||
if (is_equal(this.data, data))
|
||||
return;
|
||||
|
||||
if (data) {
|
||||
this.data = data;
|
||||
this.ifindex_cache = {};
|
||||
delete this.retry_setup_failed;
|
||||
delete this.delete;
|
||||
}
|
||||
|
||||
wdev_reset(this);
|
||||
this.config_change = true;
|
||||
this.check();
|
||||
}
|
||||
|
||||
function start()
|
||||
{
|
||||
if (this.delete)
|
||||
return;
|
||||
|
||||
this.dbg("start, state=" + this.state);
|
||||
this.autostart = true;
|
||||
|
||||
wdev_reset(this);
|
||||
|
||||
if (this.state != "down")
|
||||
return;
|
||||
|
||||
if (wdev_update_disabled_vifs(this))
|
||||
wdev_config_init(this);
|
||||
this.setup();
|
||||
}
|
||||
|
||||
|
||||
function retry_setup()
|
||||
{
|
||||
if (this.delete)
|
||||
return;
|
||||
|
||||
if (this.state != "down" || !this.autostart)
|
||||
return;
|
||||
|
||||
this.start();
|
||||
}
|
||||
|
||||
|
||||
function stop()
|
||||
{
|
||||
this.dbg("stop, state=" + this.state);
|
||||
this.autostart = false;
|
||||
|
||||
switch (this.state) {
|
||||
case "setup":
|
||||
this.cancel_setup = true;
|
||||
break;
|
||||
case "up":
|
||||
this.teardown();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function check()
|
||||
{
|
||||
if (!wdev_update_disabled_vifs(this))
|
||||
return;
|
||||
|
||||
wdev_config_init(this);
|
||||
this.setup();
|
||||
}
|
||||
|
||||
function wdev_mark_up(wdev)
|
||||
{
|
||||
wdev.dbg("mark up, state=" + wdev.state);
|
||||
if (wdev.state != "setup")
|
||||
return;
|
||||
|
||||
if (wdev.config_change) {
|
||||
wdev.setup();
|
||||
return;
|
||||
}
|
||||
|
||||
for (let section, data in wdev.handler_data) {
|
||||
if (data.ifname)
|
||||
handle_link(data.ifname, data, true);
|
||||
}
|
||||
wdev.state = "up";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
function wdev_set_data(wdev, vif, vlan, data)
|
||||
{
|
||||
let config = wdev.handler_config;
|
||||
let cur = wdev;
|
||||
let cur_type = "device";
|
||||
if (!config)
|
||||
return ubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
if (vif) {
|
||||
cur = vif = config.interfaces[vif];
|
||||
if (!vif)
|
||||
return ubus.STATUS_NOT_FOUND;
|
||||
cur_type = "vif";
|
||||
}
|
||||
|
||||
if (vlan) {
|
||||
if (!vif)
|
||||
return ubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
cur = vlan = vif.vlans[vlan];
|
||||
if (!vlan)
|
||||
return ubus.STATUS_NOT_FOUND;
|
||||
|
||||
cur_type = "vlan";
|
||||
}
|
||||
|
||||
wdev.handler_data[cur.name] = {
|
||||
...cur,
|
||||
...data,
|
||||
type: cur_type,
|
||||
config: cur.config,
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
function notify(req)
|
||||
{
|
||||
let vif = req.args.interface;
|
||||
let vlan = req.args.vlan;
|
||||
let data = req.args.data;
|
||||
|
||||
switch (req.args.command) {
|
||||
case NOTIFY_CMD_UP:
|
||||
if (vif || vlan || this.state != "setup")
|
||||
return ubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
return wdev_mark_up(this);
|
||||
case NOTIFY_CMD_SET_DATA:
|
||||
return wdev_set_data(this, vif, vlan, data);
|
||||
case NOTIFY_CMD_PROCESS_ADD:
|
||||
if (this.state != "setup" && this.state != "up")
|
||||
return 0;
|
||||
|
||||
wdev_proc_add(this, data);
|
||||
return 0;
|
||||
case NOTIFY_CMD_SET_RETRY:
|
||||
if (data.retry != null)
|
||||
this.retry = data.retry;
|
||||
else
|
||||
this.retry = DEFAULT_RETRY;
|
||||
return 0;
|
||||
default:
|
||||
return ubus.STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
function hotplug(name, add)
|
||||
{
|
||||
let dev = name;
|
||||
let m = match(name, /(.+)\.sta.+/);
|
||||
if (m)
|
||||
name = m[1];
|
||||
|
||||
for (let section, data in this.handler_data) {
|
||||
if (data.ifname != name ||
|
||||
data.type != "vif" && data.type != "vlan")
|
||||
continue;
|
||||
|
||||
handle_link(dev, data, add);
|
||||
}
|
||||
}
|
||||
|
||||
function get_status_data(wdev, vif)
|
||||
{
|
||||
let hdata = wdev.handler_data[vif.name];
|
||||
let data = {
|
||||
section: vif.name,
|
||||
config: vif.config
|
||||
};
|
||||
if (hdata && hdata.ifname)
|
||||
data.ifname = hdata.ifname;
|
||||
return data;
|
||||
}
|
||||
|
||||
function get_status_vlans(wdev, vif)
|
||||
{
|
||||
let vlans = [];
|
||||
for (let vlan in vif.vlan)
|
||||
push(vlans, get_status_data(wdev, vlan));
|
||||
return vlans;
|
||||
}
|
||||
|
||||
function get_status_stations(wdev, vif)
|
||||
{
|
||||
let vlans = [];
|
||||
for (let vlan in vif.sta)
|
||||
push(vlans, get_status_data(wdev, vlan));
|
||||
return vlans;
|
||||
}
|
||||
|
||||
function status()
|
||||
{
|
||||
let interfaces = [];
|
||||
for (let vif in this.data.vif) {
|
||||
let vlans = get_status_vlans(this, vif);
|
||||
let stations = get_status_stations(this, vif);
|
||||
let data = get_status_data(this, vif);
|
||||
push(interfaces, {
|
||||
...data,
|
||||
vlans, stations
|
||||
});
|
||||
}
|
||||
return {
|
||||
up: this.state == "up",
|
||||
pending: this.state == "setup" || this.state == "teardown",
|
||||
autostart: this.autostart,
|
||||
disabled: !!this.data.config.disabled,
|
||||
retry_setup_failed: !!this.retry_setup_failed,
|
||||
config: this.data.config,
|
||||
interfaces
|
||||
};
|
||||
}
|
||||
|
||||
function destroy()
|
||||
{
|
||||
this.dbg("destroy");
|
||||
this.autostart = false;
|
||||
this.delete = true;
|
||||
if (this.state != "down") {
|
||||
this.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
delete_wdev(this.data.name);
|
||||
}
|
||||
|
||||
function dbg(msg)
|
||||
{
|
||||
netifd.log(netifd.L_DEBUG, `wireless: ${this.name}: ${msg}\n`);
|
||||
}
|
||||
|
||||
const wdev_proto = {
|
||||
update,
|
||||
destroy,
|
||||
retry_setup,
|
||||
start,
|
||||
stop,
|
||||
setup,
|
||||
status,
|
||||
teardown,
|
||||
check,
|
||||
notify,
|
||||
hotplug,
|
||||
dbg,
|
||||
};
|
||||
|
||||
export function new(data, script, driver)
|
||||
{
|
||||
let wdev = {
|
||||
name: data.name,
|
||||
script, data,
|
||||
procs: [],
|
||||
vifs: {},
|
||||
disabled_vifs: {},
|
||||
ifindex_cache: {},
|
||||
|
||||
autostart: true,
|
||||
state: "down",
|
||||
};
|
||||
wdev_update_disabled_vifs(wdev);
|
||||
wdev_config_init(wdev);
|
||||
handler_timer = uloop.timer(1, run_next_handler);
|
||||
return proto(wdev, wdev_proto);
|
||||
};
|
||||
@@ -1,550 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import * as ubus from "ubus";
|
||||
import { realpath } from "fs";
|
||||
import {
|
||||
handler_load, handler_attributes,
|
||||
parse_attribute_list, parse_bool, parse_array,
|
||||
TYPE_ARRAY, TYPE_STRING, TYPE_INT, TYPE_BOOL
|
||||
} from "./utils.uc";
|
||||
import { find_phy } from "wifi.utils";
|
||||
import * as wdev from "./wireless-device.uc";
|
||||
|
||||
let wireless = netifd.wireless = {
|
||||
handlers: {},
|
||||
devices: {},
|
||||
mlo: {},
|
||||
path: realpath(netifd.main_path + "/wireless"),
|
||||
};
|
||||
|
||||
function wpad_update_mlo(service, mode)
|
||||
{
|
||||
let config = {};
|
||||
|
||||
for (let ifname, data in wireless.mlo) {
|
||||
if (data.mode != mode)
|
||||
continue;
|
||||
|
||||
data.phy = find_phy(data.radio_config[0], true);
|
||||
if (!data.phy)
|
||||
continue;
|
||||
|
||||
config[ifname] = data;
|
||||
}
|
||||
|
||||
ubus.call({
|
||||
object: service,
|
||||
method: "mld_set",
|
||||
return: "ignore",
|
||||
data: { config },
|
||||
});
|
||||
}
|
||||
|
||||
function hostapd_update_mlo()
|
||||
{
|
||||
wpad_update_mlo("hostapd", "ap");
|
||||
}
|
||||
|
||||
function supplicant_update_mlo()
|
||||
{
|
||||
wpad_update_mlo("wpa_supplicant", "sta");
|
||||
}
|
||||
|
||||
function update_config(new_devices, mlo_vifs)
|
||||
{
|
||||
wireless.mlo = mlo_vifs;
|
||||
hostapd_update_mlo();
|
||||
supplicant_update_mlo();
|
||||
|
||||
for (let name, dev in wireless.devices)
|
||||
if (!new_devices[name])
|
||||
dev.destroy();
|
||||
|
||||
for (let name, dev in new_devices) {
|
||||
let cur_dev = wireless.devices[name];
|
||||
if (cur_dev) {
|
||||
cur_dev.update(dev);
|
||||
continue;
|
||||
}
|
||||
|
||||
let handler = wireless.handlers[dev.config.type];
|
||||
cur_dev = wdev.new(dev, handler.script);
|
||||
if (!cur_dev)
|
||||
continue;
|
||||
|
||||
wireless.devices[name] = cur_dev;
|
||||
}
|
||||
}
|
||||
|
||||
function config_init(uci)
|
||||
{
|
||||
let config = uci.get_all("wireless");
|
||||
|
||||
let handlers = {};
|
||||
let devices = {};
|
||||
let vifs = {};
|
||||
let mlo_vifs = {};
|
||||
|
||||
let sections = {
|
||||
device: {},
|
||||
iface: {},
|
||||
vlan: {},
|
||||
station: {},
|
||||
};
|
||||
let radio_idx = {};
|
||||
let vif_idx = {};
|
||||
|
||||
for (let name, data in config) {
|
||||
let type = data[".type"];
|
||||
if (parse_bool(data.disabled) && type != "wifi-device")
|
||||
continue;
|
||||
|
||||
if (substr(type, 0, 5) != "wifi-")
|
||||
continue;
|
||||
|
||||
let list = sections[substr(type, 5)];
|
||||
if (list)
|
||||
list[name] = data;
|
||||
}
|
||||
|
||||
for (let name, data in sections.device) {
|
||||
if (!data.type)
|
||||
continue;
|
||||
|
||||
let handler = wireless.handlers[data.type];
|
||||
if (!handler)
|
||||
continue;
|
||||
|
||||
if (data.radio != null)
|
||||
radio_idx[name] = +data.radio;
|
||||
|
||||
let config = parse_attribute_list(data, handler.device);
|
||||
devices[name] = {
|
||||
name,
|
||||
config,
|
||||
|
||||
vif: [],
|
||||
};
|
||||
handlers[name] = handler;
|
||||
}
|
||||
|
||||
for (let name, data in sections.iface) {
|
||||
let dev_names = parse_array(data.device);
|
||||
let mlo_vif = parse_bool(data.mlo);
|
||||
let radios = map(dev_names, (v) => radio_idx[v]);
|
||||
radios = filter(radios, (v) => v != null);
|
||||
let radio_config = map(dev_names, (v) => devices[v].config);
|
||||
let ifname;
|
||||
|
||||
for (let dev_name in dev_names) {
|
||||
let dev = devices[dev_name];
|
||||
if (!dev || dev.config.disabled)
|
||||
continue;
|
||||
|
||||
let handler = handlers[dev_name];
|
||||
if (!handler)
|
||||
continue;
|
||||
|
||||
let config = parse_attribute_list(data, handler.iface);
|
||||
config.radios = radios;
|
||||
|
||||
if (mlo_vif && dev_name == dev_names[0]) {
|
||||
let mlo_config = { ...config };
|
||||
|
||||
mlo_config.radio_config = radio_config;
|
||||
ifname = config.ifname;
|
||||
if (!ifname) {
|
||||
let idx = vif_idx[config.mode] ?? 0;
|
||||
vif_idx[config.mode] = idx + 1;
|
||||
ifname = config.mode + "-mld" + idx;
|
||||
}
|
||||
|
||||
mlo_vifs[ifname] = mlo_config;
|
||||
}
|
||||
|
||||
if (ifname)
|
||||
config.ifname = ifname;
|
||||
if (dev_name != dev_names[0])
|
||||
delete config.macaddr;
|
||||
if (config.radio_macaddr) {
|
||||
let idx = index(dev_names, dev_name);
|
||||
let macaddr = idx >= 0 ? config.radio_macaddr[idx] : null;
|
||||
if (macaddr)
|
||||
config.macaddr = macaddr;
|
||||
}
|
||||
|
||||
let vif = {
|
||||
name, config,
|
||||
device: dev_name,
|
||||
|
||||
vlan: [],
|
||||
sta: [],
|
||||
};
|
||||
push(dev.vif, vif);
|
||||
|
||||
vifs[name] ??= [];
|
||||
push(vifs[name], vif);
|
||||
}
|
||||
}
|
||||
|
||||
for (let name, data in sections.vlan) {
|
||||
for (let iface, iface_vifs in vifs) {
|
||||
if (data.iface && data.iface != iface)
|
||||
continue;
|
||||
|
||||
for (let vif in iface_vifs) {
|
||||
let dev = devices[vif.device];
|
||||
let handler = handlers[vif.device];
|
||||
if (!dev || !handler)
|
||||
continue;
|
||||
|
||||
let config = parse_attribute_list(data, handler.vlan);
|
||||
|
||||
let vlan = {
|
||||
name,
|
||||
config
|
||||
};
|
||||
push(vif.vlan, vlan);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let name, data in sections.station) {
|
||||
if (!data.iface || !vifs[data.iface])
|
||||
continue;
|
||||
|
||||
for (let vif in vifs[data.iface]) {
|
||||
let dev = devices[vif.device];
|
||||
let handler = handlers[vif.device];
|
||||
if (!dev || !handler)
|
||||
continue;
|
||||
|
||||
let config = parse_attribute_list(data, handler.station);
|
||||
|
||||
let sta = {
|
||||
name,
|
||||
config
|
||||
};
|
||||
push(vif.sta, sta);
|
||||
}
|
||||
}
|
||||
|
||||
let udata = ubus.call({
|
||||
object: "service",
|
||||
method: "get_data",
|
||||
data: {
|
||||
type: "wifi-device"
|
||||
},
|
||||
});
|
||||
for (let svcname, svc in udata) {
|
||||
for (let insname, ins in svc) {
|
||||
for (let typename, data in ins) {
|
||||
for (let radio, config in data) {
|
||||
if (type(config) != "object")
|
||||
continue;
|
||||
|
||||
let dev = devices[radio];
|
||||
if (dev) {
|
||||
dev.config = { ...dev.config, ...config };
|
||||
continue;
|
||||
}
|
||||
|
||||
let handler = wireless.handlers[config.type];
|
||||
if (!handler)
|
||||
continue;
|
||||
|
||||
dev = devices[radio] = {
|
||||
name,
|
||||
config,
|
||||
|
||||
vif: [],
|
||||
};
|
||||
handlers[radio] = handler;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
udata = ubus.call({
|
||||
object: "service",
|
||||
method: "get_data",
|
||||
data: {
|
||||
type: "wifi-iface"
|
||||
},
|
||||
});
|
||||
|
||||
for (let svcname, svc in udata) {
|
||||
for (let insname, ins in svc) {
|
||||
for (let typename, data in ins) {
|
||||
for (let radio, vifs in data) {
|
||||
if (type(vifs) != "object")
|
||||
continue;
|
||||
|
||||
for (let name, vif in vifs) {
|
||||
let devs = vif.device;
|
||||
if (type(devs) != "array")
|
||||
devs = [ devs ];
|
||||
let config = vif.config;
|
||||
if (!config)
|
||||
continue;
|
||||
for (let device in devs) {
|
||||
let dev = devices[device];
|
||||
if (!dev)
|
||||
continue;
|
||||
|
||||
let vif_data = {
|
||||
name, device, config,
|
||||
vlan: [],
|
||||
sta: []
|
||||
};
|
||||
if (vif.vlans)
|
||||
vif_data.vlans = vif.vlans;
|
||||
if (vif.stations)
|
||||
vif_data.sta = vif.stations;
|
||||
vifs[name] ??= [];
|
||||
push(vifs[name], vif_data);
|
||||
push(dev.vif, vif_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_config(devices, mlo_vifs);
|
||||
}
|
||||
|
||||
function config_start()
|
||||
{
|
||||
for (let name, dev in wireless.devices)
|
||||
if (dev.autostart)
|
||||
dev.start();
|
||||
|
||||
}
|
||||
|
||||
function check_interfaces()
|
||||
{
|
||||
for (let name, dev in wireless.devices)
|
||||
if (dev.autostart)
|
||||
dev.check();
|
||||
}
|
||||
|
||||
function hotplug(ifname, add)
|
||||
{
|
||||
for (let name, dev in wireless.devices)
|
||||
if (dev.autostart)
|
||||
dev.hotplug(ifname, add);
|
||||
}
|
||||
|
||||
const network_config_attr = {
|
||||
network: TYPE_ARRAY,
|
||||
network_vlan: TYPE_ARRAY,
|
||||
bridge_isolate: TYPE_BOOL,
|
||||
isolate: TYPE_BOOL,
|
||||
proxy_arp: TYPE_BOOL,
|
||||
multicast_to_unicast: TYPE_BOOL,
|
||||
};
|
||||
|
||||
const default_config_attr = {
|
||||
device: {
|
||||
disabled: TYPE_BOOL,
|
||||
type: TYPE_STRING,
|
||||
},
|
||||
iface: {
|
||||
...network_config_attr,
|
||||
device: TYPE_STRING,
|
||||
mode: TYPE_STRING,
|
||||
radio_macaddr: TYPE_ARRAY,
|
||||
},
|
||||
station: {
|
||||
iface: TYPE_STRING,
|
||||
|
||||
mac: TYPE_STRING,
|
||||
key: TYPE_STRING,
|
||||
vid: TYPE_STRING,
|
||||
},
|
||||
vlan: {
|
||||
...network_config_attr,
|
||||
iface: TYPE_STRING,
|
||||
name: TYPE_STRING,
|
||||
vid: TYPE_STRING,
|
||||
},
|
||||
};
|
||||
|
||||
const wdev_args = {
|
||||
device: ""
|
||||
};
|
||||
|
||||
function wdev_call(req, cb)
|
||||
{
|
||||
let dev = req.args.device;
|
||||
if (dev) {
|
||||
dev = wireless.devices[dev];
|
||||
if (!dev)
|
||||
return ubus.STATUS_NOT_FOUND;
|
||||
|
||||
return cb(dev);
|
||||
}
|
||||
|
||||
for (let name, dev in wireless.devices)
|
||||
cb(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
function attr_validate(attr_type, validate)
|
||||
{
|
||||
if (validate)
|
||||
return validate;
|
||||
switch (attr_type) {
|
||||
case TYPE_STRING:
|
||||
return "string";
|
||||
case TYPE_ARRAY:
|
||||
return "list(string)";
|
||||
case TYPE_INT:
|
||||
return "uinteger";
|
||||
case TYPE_BOOL:
|
||||
return "bool";
|
||||
}
|
||||
}
|
||||
|
||||
function get_validate_info(ret, handler)
|
||||
{
|
||||
for (let kind in default_config_attr) {
|
||||
let cur = ret[kind == "iface" ? "interface" : kind] = {};
|
||||
let validate = handler[kind + "_validate"];
|
||||
|
||||
for (let attr, attr_type in handler[kind]) {
|
||||
let val = attr_validate(attr_type, validate[attr]);
|
||||
if (val != null)
|
||||
cur[attr] = val;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const ubus_obj = {
|
||||
up: {
|
||||
args: wdev_args,
|
||||
call: function(req) {
|
||||
hostapd_update_mlo();
|
||||
|
||||
return wdev_call(req, (dev) => {
|
||||
dev.start();
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
},
|
||||
down: {
|
||||
args: wdev_args,
|
||||
call: function(req) {
|
||||
return wdev_call(req, (dev) => {
|
||||
dev.stop();
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
},
|
||||
retry: {
|
||||
args: wdev_args,
|
||||
call: function(req) {
|
||||
hostapd_update_mlo();
|
||||
|
||||
return wdev_call(req, (dev) => {
|
||||
dev.retry_setup();
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
},
|
||||
reconf: {
|
||||
args: wdev_args,
|
||||
call: function(req) {
|
||||
hostapd_update_mlo();
|
||||
|
||||
return wdev_call(req, (dev) => {
|
||||
dev.update();
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
},
|
||||
status: {
|
||||
args: wdev_args,
|
||||
call: function(req) {
|
||||
let ret = {};
|
||||
let err = wdev_call(req, (dev) => {
|
||||
ret[dev.data.name] = dev.status();
|
||||
return 0;
|
||||
});
|
||||
if (err != 0)
|
||||
return err;
|
||||
|
||||
return ret;
|
||||
}
|
||||
},
|
||||
notify: {
|
||||
args: {
|
||||
...wdev_args,
|
||||
command: 0,
|
||||
interface: "",
|
||||
vlan: "",
|
||||
data: {},
|
||||
},
|
||||
call: function(req) {
|
||||
let dev = req.args.device;
|
||||
if (!dev)
|
||||
return ubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
dev = wireless.devices[dev];
|
||||
if (!dev)
|
||||
return ubus.STATUS_NOT_FOUND;
|
||||
|
||||
return dev.notify(req);
|
||||
}
|
||||
},
|
||||
get_validate: {
|
||||
args: wdev_args,
|
||||
call: function(req) {
|
||||
let ret = {};
|
||||
let err = wdev_call(req, (dev) => {
|
||||
let dev_type = dev.data.config.type;
|
||||
let cur = ret[dev.data.name] = {};
|
||||
get_validate_info(cur, wireless.handlers[dev_type]);
|
||||
return 0;
|
||||
});
|
||||
if (err != 0)
|
||||
return err;
|
||||
|
||||
return ret;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
handler_load(wireless.path, (script, data) => {
|
||||
if (!data.name)
|
||||
return;
|
||||
|
||||
let handler = wireless.handlers[data.name] = {
|
||||
script,
|
||||
};
|
||||
for (let kind, attr in default_config_attr) {
|
||||
let validate = handler[kind + "_validate"] = {};
|
||||
handler[kind] = handler_attributes(data[kind], attr, validate);
|
||||
}
|
||||
});
|
||||
|
||||
wireless.obj = ubus.publish("network.wireless", ubus_obj);
|
||||
wireless.listener = ubus.listener("ubus.object.add", (event, msg) => {
|
||||
if (msg.path == "hostapd")
|
||||
hostapd_update_mlo();
|
||||
else if (msg.path == "wpa_supplicant")
|
||||
supplicant_update_mlo();
|
||||
});
|
||||
|
||||
return {
|
||||
hotplug,
|
||||
config_init,
|
||||
config_start,
|
||||
check_interfaces,
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,118 +0,0 @@
|
||||
#!/usr/bin/env ucode
|
||||
import { readfile } from "fs";
|
||||
import * as uci from 'uci';
|
||||
|
||||
const bands_order = [ "6G", "5G", "2G" ];
|
||||
const htmode_order = [ "EHT", "HE", "VHT", "HT" ];
|
||||
|
||||
let board = json(readfile("/etc/board.json"));
|
||||
if (!board.wlan)
|
||||
exit(0);
|
||||
|
||||
let idx = 0;
|
||||
let commit;
|
||||
|
||||
let config = uci.cursor().get_all("wireless") ?? {};
|
||||
|
||||
function radio_exists(path, macaddr, phy, radio) {
|
||||
for (let name, s in config) {
|
||||
if (s[".type"] != "wifi-device")
|
||||
continue;
|
||||
if (radio != null && int(s.radio) != radio)
|
||||
continue;
|
||||
if (s.macaddr & lc(s.macaddr) == lc(macaddr))
|
||||
return true;
|
||||
if (s.phy == phy)
|
||||
return true;
|
||||
if (!s.path || !path)
|
||||
continue;
|
||||
if (substr(s.path, -length(path)) == path)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (let phy_name, phy in board.wlan) {
|
||||
let info = phy.info;
|
||||
if (!info || !length(info.bands))
|
||||
continue;
|
||||
|
||||
let radios = length(info.radios) > 0 ? info.radios : [{ bands: info.bands }];
|
||||
for (let radio in radios) {
|
||||
while (config[`radio${idx}`])
|
||||
idx++;
|
||||
let name = "radio" + idx;
|
||||
|
||||
let s = "wireless." + name;
|
||||
let si = "wireless.default_" + name;
|
||||
|
||||
let band_name = filter(bands_order, (b) => radio.bands[b])[0];
|
||||
if (!band_name)
|
||||
continue;
|
||||
|
||||
let band = info.bands[band_name];
|
||||
let rband = radio.bands[band_name];
|
||||
let channel = rband.default_channel ?? "auto";
|
||||
|
||||
let width = band.max_width;
|
||||
if (band_name == "2G")
|
||||
width = 20;
|
||||
else if (width > 80)
|
||||
width = 80;
|
||||
|
||||
let htmode = filter(htmode_order, (m) => band[lc(m)])[0];
|
||||
if (htmode)
|
||||
htmode += width;
|
||||
else
|
||||
htmode = "NOHT";
|
||||
|
||||
if (!phy.path)
|
||||
continue;
|
||||
|
||||
let macaddr = trim(readfile(`/sys/class/ieee80211/${phy_name}/macaddress`));
|
||||
if (radio_exists(phy.path, macaddr, phy_name, radio.index))
|
||||
continue;
|
||||
|
||||
let id = `phy='${phy_name}'`;
|
||||
if (match(phy_name, /^phy[0-9]/))
|
||||
id = `path='${phy.path}'`;
|
||||
|
||||
band_name = lc(band_name);
|
||||
|
||||
let country, defaults, num_global_macaddr;
|
||||
if (board.wlan.defaults) {
|
||||
defaults = board.wlan.defaults.ssids?.[band_name]?.ssid ? board.wlan.defaults.ssids?.[band_name] : board.wlan.defaults.ssids?.all;
|
||||
country = board.wlan.defaults.country;
|
||||
if (!country && band_name != '2g')
|
||||
defaults = null;
|
||||
num_global_macaddr = board.wlan.defaults.ssids?.[band_name]?.mac_count;
|
||||
}
|
||||
|
||||
if (length(info.radios) > 0)
|
||||
id += `\nset ${s}.radio='${radio.index}'`;
|
||||
|
||||
print(`set ${s}=wifi-device
|
||||
set ${s}.type='mac80211'
|
||||
set ${s}.${id}
|
||||
set ${s}.band='${band_name}'
|
||||
set ${s}.channel='${channel}'
|
||||
set ${s}.htmode='${htmode}'
|
||||
set ${s}.country='${country || ''}'
|
||||
set ${s}.num_global_macaddr='${num_global_macaddr || ''}'
|
||||
set ${s}.disabled='${defaults ? 1 : 0}'
|
||||
|
||||
set ${si}=wifi-iface
|
||||
set ${si}.device='${name}'
|
||||
set ${si}.network='lan'
|
||||
set ${si}.mode='ap'
|
||||
set ${si}.ssid='${defaults?.ssid || "LEDE"}'
|
||||
set ${si}.encryption='${defaults?.encryption || "none"}'
|
||||
set ${si}.key='${defaults?.key || ""}'
|
||||
|
||||
`);
|
||||
config[name] = {};
|
||||
commit = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (commit)
|
||||
print("commit wireless\n");
|
||||
@@ -1,94 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2006 OpenWrt.org
|
||||
|
||||
. /lib/functions.sh
|
||||
. /usr/share/libubox/jshn.sh
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $0 [config|up|down|reconf|reload|status|isup]
|
||||
enables (default), disables or configures devices not yet configured.
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
ubus_wifi_cmd() {
|
||||
local cmd="$1"
|
||||
local dev="$2"
|
||||
|
||||
json_init
|
||||
[ -n "$dev" ] && json_add_string device "$dev"
|
||||
ubus call network.wireless "$cmd" "$(json_dump)"
|
||||
}
|
||||
|
||||
wifi_isup() {
|
||||
local dev="$1"
|
||||
|
||||
json_load "$(ubus_wifi_cmd "status" "$dev")"
|
||||
json_get_keys devices
|
||||
|
||||
for device in $devices; do
|
||||
json_select "$device"
|
||||
json_get_var up up
|
||||
[ $up -eq 0 ] && return 1
|
||||
json_select ..
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
wifi_updown() {
|
||||
cmd=down
|
||||
[ enable = "$1" ] && {
|
||||
ubus_wifi_cmd "$cmd" "$2"
|
||||
ubus call network reload
|
||||
cmd=up
|
||||
}
|
||||
[ reconf = "$1" ] && {
|
||||
ubus call network reload
|
||||
cmd=reconf
|
||||
}
|
||||
ubus_wifi_cmd "$cmd" "$2"
|
||||
}
|
||||
|
||||
wifi_reload() {
|
||||
ubus call network reload
|
||||
}
|
||||
|
||||
wifi_detect_notice() {
|
||||
>&2 echo "WARNING: Wifi detect is deprecated. Use wifi config instead"
|
||||
>&2 echo "For more information, see commit 5f8f8a366136a07df661e31decce2458357c167a"
|
||||
exit 1
|
||||
}
|
||||
|
||||
wifi_config() {
|
||||
[ -e /tmp/.config_pending ] && return
|
||||
ucode /usr/share/hostap/wifi-detect.uc
|
||||
[ ! -f /etc/config/wireless ] && touch /etc/config/wireless
|
||||
ucode /lib/wifi/mac80211.uc | uci -q batch
|
||||
|
||||
for driver in $DRIVERS; do (
|
||||
if eval "type detect_$driver" 2>/dev/null >/dev/null; then
|
||||
eval "detect_$driver" || echo "$driver: Detect failed" >&2
|
||||
else
|
||||
echo "$driver: Hardware detection not supported" >&2
|
||||
fi
|
||||
); done
|
||||
}
|
||||
|
||||
DEVICES=
|
||||
DRIVERS=
|
||||
include /lib/wifi
|
||||
|
||||
case "$1" in
|
||||
down) wifi_updown "disable" "$2";;
|
||||
detect) wifi_detect_notice ;;
|
||||
config) wifi_config ;;
|
||||
status) ubus_wifi_cmd "status" "$2";;
|
||||
isup) wifi_isup "$2"; exit $?;;
|
||||
reload) wifi_reload "$2";;
|
||||
--help|help) usage;;
|
||||
reconf) wifi_updown "reconf" "$2";;
|
||||
''|up) wifi_updown "enable" "$2";;
|
||||
*) usage; exit 1;;
|
||||
esac
|
||||
@@ -1,423 +0,0 @@
|
||||
import * as nl80211 from "nl80211";
|
||||
import * as rtnl from "rtnl";
|
||||
import { readfile, glob, basename, readlink, open } from "fs";
|
||||
|
||||
const iftypes = {
|
||||
ap: nl80211.const.NL80211_IFTYPE_AP,
|
||||
mesh: nl80211.const.NL80211_IFTYPE_MESH_POINT,
|
||||
sta: nl80211.const.NL80211_IFTYPE_STATION,
|
||||
adhoc: nl80211.const.NL80211_IFTYPE_ADHOC,
|
||||
monitor: nl80211.const.NL80211_IFTYPE_MONITOR,
|
||||
};
|
||||
|
||||
const mesh_params = {
|
||||
mesh_retry_timeout: "retry_timeout",
|
||||
mesh_confirm_timeout: "confirm_timeout",
|
||||
mesh_holding_timeout: "holding_timeout",
|
||||
mesh_max_peer_links: "max_peer_links",
|
||||
mesh_max_retries: "max_retries",
|
||||
mesh_ttl: "ttl",
|
||||
mesh_element_ttl: "element_ttl",
|
||||
mesh_auto_open_plinks: "auto_open_plinks",
|
||||
mesh_hwmp_max_preq_retries: "hwmp_max_preq_retries",
|
||||
mesh_path_refresh_time: "path_refresh_time",
|
||||
mesh_min_discovery_timeout: "min_discovery_timeout",
|
||||
mesh_hwmp_active_path_timeout: "hwmp_active_path_timeout",
|
||||
mesh_hwmp_preq_min_interval: "hwmp_preq_min_interval",
|
||||
mesh_hwmp_net_diameter_traversal_time: "hwmp_net_diam_trvs_time",
|
||||
mesh_hwmp_rootmode: "hwmp_rootmode",
|
||||
mesh_hwmp_rann_interval: "hwmp_rann_interval",
|
||||
mesh_gate_announcements: "gate_announcements",
|
||||
mesh_sync_offset_max_neighor: "sync_offset_max_neighbor",
|
||||
mesh_rssi_threshold: "rssi_threshold",
|
||||
mesh_hwmp_active_path_to_root_timeout: "hwmp_path_to_root_timeout",
|
||||
mesh_hwmp_root_interval: "hwmp_root_interval",
|
||||
mesh_hwmp_confirmation_interval: "hwmp_confirmation_interval",
|
||||
mesh_awake_window: "awake_window",
|
||||
mesh_plink_timeout: "plink_timeout",
|
||||
mesh_fwding: "forwarding",
|
||||
mesh_power_mode: "power_mode",
|
||||
mesh_nolearn: "nolearn"
|
||||
};
|
||||
|
||||
function wdev_remove(name)
|
||||
{
|
||||
nl80211.request(nl80211.const.NL80211_CMD_DEL_INTERFACE, 0, { dev: name });
|
||||
}
|
||||
|
||||
function __phy_is_fullmac(phyidx)
|
||||
{
|
||||
let data = nl80211.request(nl80211.const.NL80211_CMD_GET_WIPHY, 0, { wiphy: phyidx });
|
||||
|
||||
return !data.software_iftypes.monitor;
|
||||
}
|
||||
|
||||
function phy_is_fullmac(phy)
|
||||
{
|
||||
let phyidx = int(trim(readfile(`/sys/class/ieee80211/${phy}/index`)));
|
||||
|
||||
return __phy_is_fullmac(phyidx);
|
||||
}
|
||||
|
||||
function find_reusable_wdev(phyidx)
|
||||
{
|
||||
if (!__phy_is_fullmac(phyidx))
|
||||
return null;
|
||||
|
||||
let data = nl80211.request(
|
||||
nl80211.const.NL80211_CMD_GET_INTERFACE,
|
||||
nl80211.const.NLM_F_DUMP,
|
||||
{ wiphy: phyidx });
|
||||
for (let res in data)
|
||||
if (trim(readfile(`/sys/class/net/${res.ifname}/operstate`)) == "down")
|
||||
return res.ifname;
|
||||
return null;
|
||||
}
|
||||
|
||||
function wdev_set_radio_mask(name, mask)
|
||||
{
|
||||
nl80211.request(nl80211.const.NL80211_CMD_SET_INTERFACE, 0, {
|
||||
dev: name,
|
||||
vif_radio_mask: mask
|
||||
});
|
||||
}
|
||||
|
||||
function wdev_create(phy, name, data)
|
||||
{
|
||||
let phyidx = int(readfile(`/sys/class/ieee80211/${phy}/index`));
|
||||
|
||||
wdev_remove(name);
|
||||
|
||||
if (!iftypes[data.mode])
|
||||
return `Invalid mode: ${data.mode}`;
|
||||
|
||||
let req = {
|
||||
wiphy: phyidx,
|
||||
ifname: name,
|
||||
iftype: iftypes[data.mode],
|
||||
};
|
||||
|
||||
if (data["4addr"])
|
||||
req["4addr"] = data["4addr"];
|
||||
if (data.macaddr)
|
||||
req.mac = data.macaddr;
|
||||
if (data.radio_mask > 0)
|
||||
req.vif_radio_mask = data.radio_mask;
|
||||
else if (data.radio != null && data.radio >= 0)
|
||||
req.vif_radio_mask = 1 << data.radio;
|
||||
|
||||
nl80211.error();
|
||||
|
||||
let reuse_ifname = find_reusable_wdev(phyidx);
|
||||
if (reuse_ifname &&
|
||||
(reuse_ifname == name ||
|
||||
rtnl.request(rtnl.const.RTM_SETLINK, 0, { dev: reuse_ifname, ifname: name}) != false)) {
|
||||
req.dev = req.ifname;
|
||||
delete req.ifname;
|
||||
nl80211.request(nl80211.const.NL80211_CMD_SET_INTERFACE, 0, req);
|
||||
} else {
|
||||
nl80211.request(
|
||||
nl80211.const.NL80211_CMD_NEW_INTERFACE,
|
||||
nl80211.const.NLM_F_CREATE,
|
||||
req);
|
||||
}
|
||||
|
||||
let error = nl80211.error();
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (data.powersave != null) {
|
||||
nl80211.request(nl80211.const.NL80211_CMD_SET_POWER_SAVE, 0,
|
||||
{ dev: name, ps_state: data.powersave ? 1 : 0});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function wdev_set_mesh_params(name, data)
|
||||
{
|
||||
let mesh_cfg = {};
|
||||
|
||||
for (let key in mesh_params) {
|
||||
let val = data[key];
|
||||
if (val == null)
|
||||
continue;
|
||||
mesh_cfg[mesh_params[key]] = int(val);
|
||||
}
|
||||
|
||||
if (!length(mesh_cfg))
|
||||
return null;
|
||||
|
||||
nl80211.request(nl80211.const.NL80211_CMD_SET_MESH_CONFIG, 0,
|
||||
{ dev: name, mesh_params: mesh_cfg });
|
||||
|
||||
return nl80211.error();
|
||||
}
|
||||
|
||||
function wdev_set_up(name, up)
|
||||
{
|
||||
rtnl.request(rtnl.const.RTM_SETLINK, 0, { dev: name, change: 1, flags: up ? 1 : 0 });
|
||||
}
|
||||
|
||||
function phy_sysfs_file(phy, name)
|
||||
{
|
||||
return trim(readfile(`/sys/class/ieee80211/${phy}/${name}`));
|
||||
}
|
||||
|
||||
function macaddr_split(str)
|
||||
{
|
||||
return map(split(str, ":"), (val) => hex(val));
|
||||
}
|
||||
|
||||
function macaddr_join(addr)
|
||||
{
|
||||
return join(":", map(addr, (val) => sprintf("%02x", val)));
|
||||
}
|
||||
|
||||
function wdev_macaddr(wdev)
|
||||
{
|
||||
return trim(readfile(`/sys/class/net/${wdev}/address`));
|
||||
}
|
||||
|
||||
const phy_proto = {
|
||||
macaddr_init: function(used, options) {
|
||||
this.macaddr_options = options ?? {};
|
||||
this.macaddr_list = {};
|
||||
|
||||
if (type(used) == "object")
|
||||
for (let addr in used)
|
||||
this.macaddr_list[addr] = used[addr];
|
||||
else
|
||||
for (let addr in used)
|
||||
this.macaddr_list[addr] = -1;
|
||||
|
||||
this.for_each_wdev((wdev) => {
|
||||
let macaddr = wdev_macaddr(wdev);
|
||||
this.macaddr_list[macaddr] ??= -1;
|
||||
});
|
||||
|
||||
return this.macaddr_list;
|
||||
},
|
||||
|
||||
macaddr_generate: function(data) {
|
||||
let phy = this.phy;
|
||||
let radio_idx = this.radio;
|
||||
let idx = int(data.id ?? 0);
|
||||
let mbssid = int(data.mbssid ?? 0) > 0;
|
||||
let num_global = int(data.num_global ?? 1);
|
||||
let use_global = !mbssid && idx < num_global;
|
||||
|
||||
let base_addr = phy_sysfs_file(phy, "macaddress");
|
||||
if (!base_addr)
|
||||
return null;
|
||||
|
||||
let base_mask = phy_sysfs_file(phy, "address_mask");
|
||||
if (!base_mask)
|
||||
return null;
|
||||
|
||||
if (base_mask == "00:00:00:00:00:00")
|
||||
base_mask = "ff:ff:ff:ff:ff:ff";
|
||||
|
||||
if (data.macaddr_base)
|
||||
base_addr = data.macaddr_base;
|
||||
else if (base_mask == "ff:ff:ff:ff:ff:ff" &&
|
||||
(radio_idx > 0 || idx >= num_global)) {
|
||||
let addrs = split(phy_sysfs_file(phy, "addresses"), "\n");
|
||||
|
||||
if (radio_idx != null) {
|
||||
if (radio_idx && radio_idx < length(addrs))
|
||||
base_addr = addrs[radio_idx];
|
||||
else
|
||||
idx += radio_idx * 16;
|
||||
} else {
|
||||
if (idx < length(addrs))
|
||||
return addrs[idx];
|
||||
}
|
||||
}
|
||||
|
||||
if (!idx && !mbssid)
|
||||
return base_addr;
|
||||
|
||||
let addr = macaddr_split(base_addr);
|
||||
let mask = macaddr_split(base_mask);
|
||||
let type;
|
||||
|
||||
if (mbssid)
|
||||
type = "b5";
|
||||
else if (use_global)
|
||||
type = "add";
|
||||
else if (mask[0] > 0)
|
||||
type = "b1";
|
||||
else if (mask[5] < 0xff)
|
||||
type = "b5";
|
||||
else
|
||||
type = "add";
|
||||
|
||||
switch (type) {
|
||||
case "b1":
|
||||
if (!(addr[0] & 2))
|
||||
idx--;
|
||||
addr[0] |= 2;
|
||||
addr[0] ^= idx << 2;
|
||||
break;
|
||||
case "b5":
|
||||
if (mbssid)
|
||||
addr[0] |= 2;
|
||||
addr[5] ^= idx;
|
||||
break;
|
||||
default:
|
||||
for (let i = 5; i > 0; i--) {
|
||||
addr[i] += idx;
|
||||
if (addr[i] < 256)
|
||||
break;
|
||||
addr[i] %= 256;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return macaddr_join(addr);
|
||||
},
|
||||
|
||||
macaddr_next: function(val) {
|
||||
let data = this.macaddr_options ?? {};
|
||||
let list = this.macaddr_list;
|
||||
|
||||
for (let i = 0; i < 32; i++) {
|
||||
data.id = i;
|
||||
|
||||
let mac = this.macaddr_generate(data);
|
||||
if (!mac)
|
||||
return null;
|
||||
|
||||
if (list[mac] != null)
|
||||
continue;
|
||||
|
||||
list[mac] = val != null ? val : -1;
|
||||
return mac;
|
||||
}
|
||||
},
|
||||
|
||||
wdev_add: function(name, data) {
|
||||
let phydev = this;
|
||||
wdev_create(this.phy, name, {
|
||||
...data,
|
||||
radio: this.radio,
|
||||
});
|
||||
},
|
||||
|
||||
for_each_wdev: function(cb) {
|
||||
let wdevs = nl80211.request(
|
||||
nl80211.const.NL80211_CMD_GET_INTERFACE,
|
||||
nl80211.const.NLM_F_DUMP,
|
||||
{ wiphy: this.idx }
|
||||
);
|
||||
|
||||
let mac_wdev = {};
|
||||
for (let wdev in wdevs) {
|
||||
if (wdev.iftype == nl80211.const.NL80211_IFTYPE_AP_VLAN)
|
||||
continue;
|
||||
if (this.radio != null && wdev.vif_radio_mask != null &&
|
||||
wdev.vif_radio_mask != (1 << this.radio))
|
||||
continue;
|
||||
mac_wdev[wdev.mac] = wdev;
|
||||
}
|
||||
|
||||
for (let wdev in wdevs) {
|
||||
if (!mac_wdev[wdev.mac])
|
||||
continue;
|
||||
|
||||
cb(wdev.ifname);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function phy_open(phy, radio)
|
||||
{
|
||||
let phyidx = readfile(`/sys/class/ieee80211/${phy}/index`);
|
||||
if (!phyidx)
|
||||
return null;
|
||||
|
||||
let name = phy;
|
||||
if (radio === "" || radio < 0)
|
||||
radio = null;
|
||||
if (radio != null)
|
||||
name += "." + radio;
|
||||
|
||||
return proto({
|
||||
phy, name, radio,
|
||||
idx: int(phyidx),
|
||||
}, phy_proto);
|
||||
}
|
||||
|
||||
const vlist_proto = {
|
||||
update: function(values, arg) {
|
||||
let data = this.data;
|
||||
let cb = this.cb;
|
||||
let seq = { };
|
||||
let new_data = {};
|
||||
let old_data = {};
|
||||
|
||||
this.data = new_data;
|
||||
|
||||
if (type(values) == "object") {
|
||||
for (let key in values) {
|
||||
old_data[key] = data[key];
|
||||
new_data[key] = values[key];
|
||||
delete data[key];
|
||||
}
|
||||
} else {
|
||||
for (let val in values) {
|
||||
let cur_key = val[0];
|
||||
let cur_obj = val[1];
|
||||
|
||||
old_data[cur_key] = data[cur_key];
|
||||
new_data[cur_key] = val[1];
|
||||
delete data[cur_key];
|
||||
}
|
||||
}
|
||||
|
||||
for (let key in data) {
|
||||
cb(null, data[key], arg);
|
||||
delete data[key];
|
||||
}
|
||||
for (let key in new_data)
|
||||
cb(new_data[key], old_data[key], arg);
|
||||
}
|
||||
};
|
||||
|
||||
function is_equal(val1, val2) {
|
||||
let t1 = type(val1);
|
||||
|
||||
if (t1 != type(val2))
|
||||
return false;
|
||||
|
||||
if (t1 == "array") {
|
||||
if (length(val1) != length(val2))
|
||||
return false;
|
||||
|
||||
for (let i = 0; i < length(val1); i++)
|
||||
if (!is_equal(val1[i], val2[i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
} else if (t1 == "object") {
|
||||
for (let key in val1)
|
||||
if (!is_equal(val1[key], val2[key]))
|
||||
return false;
|
||||
for (let key in val2)
|
||||
if (val1[key] == null)
|
||||
return false;
|
||||
return true;
|
||||
} else {
|
||||
return val1 == val2;
|
||||
}
|
||||
}
|
||||
|
||||
function vlist_new(cb) {
|
||||
return proto({
|
||||
cb: cb,
|
||||
data: {}
|
||||
}, vlist_proto);
|
||||
}
|
||||
|
||||
export { wdev_remove, wdev_create, wdev_set_mesh_params, wdev_set_radio_mask, wdev_set_up, is_equal, vlist_new, phy_is_fullmac, phy_open };
|
||||
@@ -1,183 +0,0 @@
|
||||
#!/usr/bin/env ucode
|
||||
'use strict';
|
||||
import { vlist_new, is_equal, wdev_set_mesh_params, wdev_remove, wdev_set_up, phy_open } from "/usr/share/hostap/common.uc";
|
||||
import { readfile, writefile, basename, readlink, glob } from "fs";
|
||||
let libubus = require("ubus");
|
||||
|
||||
let keep_devices = {};
|
||||
let phy_name = shift(ARGV);
|
||||
let command = shift(ARGV);
|
||||
let phy, phydev;
|
||||
|
||||
function iface_stop(wdev)
|
||||
{
|
||||
if (keep_devices[wdev.ifname])
|
||||
return;
|
||||
|
||||
wdev_remove(wdev.ifname);
|
||||
}
|
||||
|
||||
function iface_start(wdev)
|
||||
{
|
||||
let ifname = wdev.ifname;
|
||||
|
||||
if (readfile(`/sys/class/net/${ifname}/ifindex`)) {
|
||||
wdev_set_up(ifname, false);
|
||||
wdev_remove(ifname);
|
||||
}
|
||||
let wdev_config = {};
|
||||
for (let key in wdev)
|
||||
wdev_config[key] = wdev[key];
|
||||
if (!wdev_config.macaddr && wdev.mode != "monitor")
|
||||
wdev_config.macaddr = phydev.macaddr_next();
|
||||
phydev.wdev_add(ifname, wdev_config);
|
||||
wdev_set_up(ifname, true);
|
||||
let htmode = wdev.htmode || "NOHT";
|
||||
if (wdev.freq)
|
||||
system(`iw dev ${ifname} set freq ${wdev.freq} ${htmode}`);
|
||||
if (wdev.mode == "adhoc") {
|
||||
let cmd = ["iw", "dev", ifname, "ibss", "join", wdev.ssid, wdev.freq, htmode, "fixed-freq" ];
|
||||
if (wdev.bssid)
|
||||
push(cmd, wdev.bssid);
|
||||
for (let key in [ "beacon-interval", "basic-rates", "mcast-rate", "keys" ])
|
||||
if (wdev[key])
|
||||
push(cmd, key, wdev[key]);
|
||||
system(cmd);
|
||||
} else if (wdev.mode == "mesh") {
|
||||
let cmd = [ "iw", "dev", ifname, "mesh", "join", wdev.ssid, "freq", wdev.freq, htmode ];
|
||||
for (let key in [ "basic-rates", "mcast-rate", "beacon-interval" ])
|
||||
if (wdev[key])
|
||||
push(cmd, key, wdev[key]);
|
||||
system(cmd);
|
||||
|
||||
wdev_set_mesh_params(ifname, wdev);
|
||||
}
|
||||
}
|
||||
|
||||
function iface_cb(new_if, old_if)
|
||||
{
|
||||
if (old_if && new_if && is_equal(old_if, new_if))
|
||||
return;
|
||||
|
||||
if (old_if)
|
||||
iface_stop(old_if);
|
||||
if (new_if)
|
||||
iface_start(new_if);
|
||||
}
|
||||
|
||||
function drop_inactive(config)
|
||||
{
|
||||
for (let key in config) {
|
||||
if (!readfile(`/sys/class/net/${key}/ifindex`))
|
||||
delete config[key];
|
||||
}
|
||||
}
|
||||
|
||||
function add_ifname(config)
|
||||
{
|
||||
for (let key in config)
|
||||
config[key].ifname = key;
|
||||
}
|
||||
|
||||
function delete_ifname(config)
|
||||
{
|
||||
for (let key in config)
|
||||
delete config[key].ifname;
|
||||
}
|
||||
|
||||
function add_existing(phydev, config)
|
||||
{
|
||||
phydev.for_each_wdev((wdev) => {
|
||||
if (config[wdev])
|
||||
return;
|
||||
|
||||
if (trim(readfile(`/sys/class/net/${wdev}/operstate`)) == "down")
|
||||
config[wdev] = {};
|
||||
});
|
||||
}
|
||||
|
||||
function usage()
|
||||
{
|
||||
warn(`Usage: ${basename(sourcepath())} <phy> <command> [<arguments>]
|
||||
|
||||
Commands:
|
||||
set_config <config> [<device]...] - set phy configuration
|
||||
get_macaddr <id> - get phy MAC address for vif index <id>
|
||||
`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const commands = {
|
||||
set_config: function(args) {
|
||||
let statefile = `/var/run/wdev-${phy_name}.json`;
|
||||
|
||||
let new_config = shift(args);
|
||||
for (let dev in ARGV)
|
||||
keep_devices[dev] = true;
|
||||
|
||||
if (!new_config)
|
||||
usage();
|
||||
|
||||
new_config = json(new_config);
|
||||
if (!new_config) {
|
||||
warn("Invalid configuration\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
let old_config = readfile(statefile);
|
||||
if (old_config)
|
||||
old_config = json(old_config);
|
||||
|
||||
let config = vlist_new(iface_cb);
|
||||
if (type(old_config) == "object")
|
||||
config.data = old_config;
|
||||
|
||||
add_existing(phydev, config.data);
|
||||
add_ifname(config.data);
|
||||
drop_inactive(config.data);
|
||||
|
||||
let ubus = libubus.connect();
|
||||
let data = ubus.call("hostapd", "config_get_macaddr_list", { phy: phydev.name, radio: phydev.radio ?? -1 });
|
||||
let macaddr_list = [];
|
||||
if (type(data) == "object" && data.macaddr)
|
||||
macaddr_list = data.macaddr;
|
||||
ubus.disconnect();
|
||||
phydev.macaddr_init(macaddr_list);
|
||||
|
||||
add_ifname(new_config);
|
||||
config.update(new_config);
|
||||
|
||||
drop_inactive(config.data);
|
||||
delete_ifname(config.data);
|
||||
writefile(statefile, sprintf("%J", config.data));
|
||||
},
|
||||
get_macaddr: function(args) {
|
||||
let data = {};
|
||||
|
||||
for (let arg in args) {
|
||||
arg = split(arg, "=", 2);
|
||||
data[arg[0]] = arg[1];
|
||||
}
|
||||
|
||||
let macaddr = phydev.macaddr_generate(data);
|
||||
if (!macaddr) {
|
||||
warn(`Could not get MAC address for phy ${phy_name}\n`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
print(macaddr + "\n");
|
||||
},
|
||||
};
|
||||
|
||||
if (!phy_name || !command | !commands[command])
|
||||
usage();
|
||||
|
||||
let phy_split = split(phy_name, ":");
|
||||
phydev = phy_open(phy_split[0], phy_split[1]);
|
||||
phy = phydev.phy;
|
||||
if (!phydev) {
|
||||
warn(`PHY ${phy_name} does not exist\n`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
commands[command](ARGV);
|
||||
@@ -1,260 +0,0 @@
|
||||
#!/usr/bin/env ucode
|
||||
'use strict';
|
||||
import { readfile, writefile, realpath, glob, basename, unlink, open, rename } from "fs";
|
||||
import { is_equal } from "/usr/share/hostap/common.uc";
|
||||
let nl = require("nl80211");
|
||||
|
||||
let board_file = "/etc/board.json";
|
||||
let prev_board_data = json(readfile(board_file));
|
||||
let board_data = json(readfile(board_file));
|
||||
|
||||
function phy_idx(name) {
|
||||
return +rtrim(readfile(`/sys/class/ieee80211/${name}/index`));
|
||||
}
|
||||
|
||||
function phy_path(name) {
|
||||
let devpath = realpath(`/sys/class/ieee80211/${name}/device`);
|
||||
|
||||
devpath = replace(devpath, /^\/sys\/devices\//, "");
|
||||
if (match(devpath, /^platform\/.*\/pci/))
|
||||
devpath = replace(devpath, /^platform\//, "");
|
||||
let dev_phys = map(glob(`/sys/class/ieee80211/${name}/device/ieee80211/*`), basename);
|
||||
sort(dev_phys, (a, b) => phy_idx(a) - phy_idx(b));
|
||||
|
||||
let ofs = index(dev_phys, name);
|
||||
if (ofs > 0)
|
||||
devpath += `+${ofs}`;
|
||||
|
||||
return devpath;
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
let wlan = board_data.wlan;
|
||||
|
||||
for (let name in wlan)
|
||||
if (substr(name, 0, 3) == "phy")
|
||||
delete wlan[name];
|
||||
else
|
||||
delete wlan[name].info;
|
||||
}
|
||||
|
||||
function wiphy_get_entry(phy, path) {
|
||||
board_data.wlan ??= {};
|
||||
|
||||
let wlan = board_data.wlan;
|
||||
for (let name in wlan)
|
||||
if (wlan[name].path == path)
|
||||
return wlan[name];
|
||||
|
||||
wlan[phy] = {
|
||||
path: path
|
||||
};
|
||||
|
||||
return wlan[phy];
|
||||
}
|
||||
|
||||
function freq_to_channel(freq) {
|
||||
if (freq < 1000)
|
||||
return 0;
|
||||
if (freq == 2484)
|
||||
return 14;
|
||||
if (freq == 5935)
|
||||
return 2;
|
||||
if (freq < 2484)
|
||||
return (freq - 2407) / 5;
|
||||
if (freq >= 4910 && freq <= 4980)
|
||||
return (freq - 4000) / 5;
|
||||
if (freq < 5950)
|
||||
return (freq - 5000) / 5;
|
||||
if (freq <= 45000)
|
||||
return (freq - 5950) / 5;
|
||||
if (freq >= 58320 && freq <= 70200)
|
||||
return (freq - 56160) / 2160;
|
||||
return 0;
|
||||
}
|
||||
|
||||
function freq_range_match(ranges, freq) {
|
||||
freq *= 1000;
|
||||
for (let range in ranges) {
|
||||
if (freq >= range[0] && freq <= range[1])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function wiphy_detect() {
|
||||
let phys = nl.request(nl.const.NL80211_CMD_GET_WIPHY, nl.const.NLM_F_DUMP, { split_wiphy_dump: true });
|
||||
if (!phys)
|
||||
return;
|
||||
|
||||
for (let phy in phys) {
|
||||
if (!phy)
|
||||
continue;
|
||||
|
||||
let name = phy.wiphy_name;
|
||||
let path = phy_path(name);
|
||||
let info = {
|
||||
antenna_rx: phy.wiphy_antenna_avail_rx,
|
||||
antenna_tx: phy.wiphy_antenna_avail_tx,
|
||||
bands: {},
|
||||
radios: []
|
||||
};
|
||||
|
||||
for (let radio in phy.radios) {
|
||||
// S1G is not supported yet
|
||||
radio.freq_ranges = filter(radio.freq_ranges,
|
||||
(range) => range.end > 2000000
|
||||
);
|
||||
|
||||
if (!length(radio.freq_ranges))
|
||||
continue;
|
||||
|
||||
push(info.radios, {
|
||||
index: radio.index,
|
||||
freq_ranges: map(radio.freq_ranges,
|
||||
(range) => [ range.start, range.end ]
|
||||
),
|
||||
bands: {}
|
||||
});
|
||||
}
|
||||
|
||||
let bands = info.bands;
|
||||
for (let band in phy.wiphy_bands) {
|
||||
if (!band || !band.freqs)
|
||||
continue;
|
||||
let freq = band.freqs[0].freq;
|
||||
let band_info = {};
|
||||
let band_name;
|
||||
if (freq > 50000)
|
||||
band_name = "60G";
|
||||
else if (freq > 5900)
|
||||
band_name = "6G";
|
||||
else if (freq > 4000)
|
||||
band_name = "5G";
|
||||
else if (freq > 2000)
|
||||
band_name = "2G";
|
||||
else
|
||||
continue;
|
||||
bands[band_name] = band_info;
|
||||
if (band.ht_capa > 0)
|
||||
band_info.ht = true;
|
||||
if (band.vht_capa > 0)
|
||||
band_info.vht = true;
|
||||
let he_phy_cap = 0;
|
||||
let eht_phy_cap = 0;
|
||||
|
||||
for (let ift in band.iftype_data) {
|
||||
if (!ift.he_cap_phy)
|
||||
continue;
|
||||
|
||||
band_info.he = true;
|
||||
he_phy_cap |= ift.he_cap_phy[0];
|
||||
|
||||
if (!ift.eht_cap_phy)
|
||||
continue;
|
||||
|
||||
band_info.eht = true;
|
||||
eht_phy_cap |= ift.eht_cap_phy[0];
|
||||
}
|
||||
|
||||
if (band_name != "2G" &&
|
||||
(he_phy_cap & 0x18) || ((band.vht_capa >> 2) & 0x3))
|
||||
band_info.max_width = 160;
|
||||
else if (band_name != "2G" &&
|
||||
(he_phy_cap & 4) || band.vht_capa > 0)
|
||||
band_info.max_width = 80;
|
||||
else if ((band.ht_capa & 0x2) || (he_phy_cap & 0x2))
|
||||
band_info.max_width = 40;
|
||||
else
|
||||
band_info.max_width = 20;
|
||||
|
||||
let modes = band_info.modes = [ "NOHT" ];
|
||||
if (band_info.ht)
|
||||
push(modes, "HT20");
|
||||
if (band_info.vht)
|
||||
push(modes, "VHT20");
|
||||
if (band_info.he)
|
||||
push(modes, "HE20");
|
||||
if (band_info.eht)
|
||||
push(modes, "EHT20");
|
||||
if (band.ht_capa & 0x2) {
|
||||
push(modes, "HT40");
|
||||
if (band_info.vht)
|
||||
push(modes, "VHT40")
|
||||
}
|
||||
if (he_phy_cap & 2)
|
||||
push(modes, "HE40");
|
||||
|
||||
if (eht_phy_cap && he_phy_cap & 2)
|
||||
push(modes, "EHT40");
|
||||
|
||||
for (let radio in info.radios) {
|
||||
let freq_match = filter(band.freqs,
|
||||
(freq) => freq_range_match(radio.freq_ranges, freq.freq)
|
||||
);
|
||||
if (!length(freq_match))
|
||||
continue;
|
||||
|
||||
let radio_band = {};
|
||||
radio.bands[band_name] = radio_band;
|
||||
|
||||
freq_match = filter(freq_match,
|
||||
(freq) => !freq.disabled
|
||||
);
|
||||
|
||||
let freq = freq_match[0];
|
||||
if (freq)
|
||||
radio_band.default_channel = freq_to_channel(freq.freq);
|
||||
}
|
||||
|
||||
for (let freq in band.freqs) {
|
||||
if (freq.disabled)
|
||||
continue;
|
||||
let chan = freq_to_channel(freq.freq);
|
||||
if (!chan)
|
||||
continue;
|
||||
band_info.default_channel = chan;
|
||||
break;
|
||||
}
|
||||
|
||||
if (band_name == "2G")
|
||||
continue;
|
||||
|
||||
if (he_phy_cap & 4)
|
||||
push(modes, "HE40");
|
||||
if (eht_phy_cap && he_phy_cap & 4)
|
||||
push(modes, "EHT40");
|
||||
if (band_info.vht)
|
||||
push(modes, "VHT80");
|
||||
if (he_phy_cap & 4)
|
||||
push(modes, "HE80");
|
||||
if (eht_phy_cap && he_phy_cap & 4)
|
||||
push(modes, "EHT80");
|
||||
if ((band.vht_capa >> 2) & 0x3)
|
||||
push(modes, "VHT160");
|
||||
if (he_phy_cap & 0x18)
|
||||
push(modes, "HE160");
|
||||
if (eht_phy_cap && he_phy_cap & 0x18)
|
||||
push(modes, "EHT160");
|
||||
|
||||
if (eht_phy_cap & 2)
|
||||
push(modes, "EHT320");
|
||||
}
|
||||
|
||||
let entry = wiphy_get_entry(name, path);
|
||||
entry.info = info;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup();
|
||||
wiphy_detect();
|
||||
if (!is_equal(prev_board_data, board_data)) {
|
||||
let new_file = board_file + ".new";
|
||||
unlink(new_file);
|
||||
let f = open(new_file, "wx");
|
||||
if (!f)
|
||||
exit(1);
|
||||
f.write(sprintf("%.J\n", board_data));
|
||||
f.close();
|
||||
rename(new_file, board_file);
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import { readfile, realpath, lsdir } from "fs";
|
||||
import * as nl80211 from "nl80211";
|
||||
|
||||
function phy_filename(phy, name) {
|
||||
return `/sys/class/ieee80211/${phy}/${name}`;
|
||||
}
|
||||
|
||||
function phy_file(phy, name) {
|
||||
return readfile(phy_filename(phy, name));
|
||||
}
|
||||
|
||||
function phy_index(phy) {
|
||||
return +phy_file(phy, "index");
|
||||
}
|
||||
|
||||
function phy_path_match(phy, path) {
|
||||
let phy_path = realpath(phy_filename(phy, "device"));
|
||||
return substr(phy_path, -length(path)) == path;
|
||||
}
|
||||
|
||||
function __find_phy_by_path(phys, path) {
|
||||
if (!path)
|
||||
return null;
|
||||
|
||||
path = split(path, "+");
|
||||
phys = filter(phys, (phy) => phy_path_match(phy, path[0]));
|
||||
phys = sort(phys, (a, b) => phy_index(a) - phy_index(b));
|
||||
|
||||
return phys[+path[1]];
|
||||
}
|
||||
|
||||
function find_phy_by_macaddr(phys, macaddr) {
|
||||
macaddr = lc(macaddr);
|
||||
return filter(phys, (phy) => phy_file(phy, "macaddr") == macaddr)[0];
|
||||
}
|
||||
|
||||
function rename_phy_by_name(phys, name, rename) {
|
||||
let data = json(readfile("/etc/board.json")).wlan;
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
data = data[name];
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
let prev_name = __find_phy_by_path(phys, data.path);
|
||||
if (!prev_name)
|
||||
return;
|
||||
|
||||
if (!rename)
|
||||
return true;
|
||||
|
||||
let idx = phy_index(prev_name);
|
||||
nl80211.request(nl80211.const.NL80211_CMD_SET_WIPHY, 0, {
|
||||
wiphy: idx,
|
||||
wiphy_name: name
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
function find_phy_by_path(phys, path) {
|
||||
let name = __find_phy_by_path(phys, path);
|
||||
if (!name)
|
||||
return;
|
||||
|
||||
let data = json(readfile("/etc/board.json")).wlan;
|
||||
if (!data || data[name])
|
||||
return name;
|
||||
|
||||
for (let cur_name, cur_data in data) {
|
||||
if (!phy_path_match(name, cur_data.path))
|
||||
continue;
|
||||
|
||||
let idx = phy_index(name);
|
||||
nl80211.request(nl80211.const.NL80211_CMD_SET_WIPHY, 0, {
|
||||
wiphy: idx,
|
||||
wiphy_name: cur_name
|
||||
});
|
||||
|
||||
return cur_name;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
function find_phy_by_name(phys, name, rename) {
|
||||
if (index(phys, name) >= 0)
|
||||
return name;
|
||||
|
||||
if (!rename_phy_by_name(phys, name, rename))
|
||||
return;
|
||||
|
||||
if (!rename)
|
||||
return name;
|
||||
|
||||
return index(phys, name) < 0 ? null : name;
|
||||
}
|
||||
|
||||
export function find_phy(config, rename) {
|
||||
let phys = lsdir("/sys/class/ieee80211");
|
||||
|
||||
return find_phy_by_path(phys, config.path) ??
|
||||
find_phy_by_macaddr(phys, config.macaddr) ??
|
||||
find_phy_by_name(phys, config.phy, rename);
|
||||
};
|
||||
@@ -1,12 +1,54 @@
|
||||
# wpa_supplicant config
|
||||
config WPA_RFKILL_SUPPORT
|
||||
bool "Add rfkill support"
|
||||
depends on PACKAGE_hostapd-common
|
||||
depends on PACKAGE_wpa-supplicant || \
|
||||
PACKAGE_wpa-supplicant-openssl || \
|
||||
PACKAGE_wpa-supplicant-wolfssl || \
|
||||
PACKAGE_wpa-supplicant-mbedtls || \
|
||||
PACKAGE_wpa-supplicant-mesh-openssl || \
|
||||
PACKAGE_wpa-supplicant-mesh-wolfssl || \
|
||||
PACKAGE_wpa-supplicant-mesh-mbedtls || \
|
||||
PACKAGE_wpa-supplicant-basic || \
|
||||
PACKAGE_wpa-supplicant-mini || \
|
||||
PACKAGE_wpa-supplicant-p2p || \
|
||||
PACKAGE_wpad || \
|
||||
PACKAGE_wpad-openssl || \
|
||||
PACKAGE_wpad-wolfssl || \
|
||||
PACKAGE_wpad-mbedtls || \
|
||||
PACKAGE_wpad-basic || \
|
||||
PACKAGE_wpad-basic-openssl || \
|
||||
PACKAGE_wpad-basic-wolfssl || \
|
||||
PACKAGE_wpad-basic-mbedtls || \
|
||||
PACKAGE_wpad-mini || \
|
||||
PACKAGE_wpad-mesh-openssl || \
|
||||
PACKAGE_wpad-mesh-wolfssl || \
|
||||
PACKAGE_wpad-mesh-mbedtls
|
||||
default n
|
||||
|
||||
config WPA_MSG_MIN_PRIORITY
|
||||
int "Minimum debug message priority"
|
||||
depends on PACKAGE_hostapd-common
|
||||
depends on PACKAGE_wpa-supplicant || \
|
||||
PACKAGE_wpa-supplicant-openssl || \
|
||||
PACKAGE_wpa-supplicant-wolfssl || \
|
||||
PACKAGE_wpa-supplicant-mbedtls || \
|
||||
PACKAGE_wpa-supplicant-mesh-openssl || \
|
||||
PACKAGE_wpa-supplicant-mesh-wolfssl || \
|
||||
PACKAGE_wpa-supplicant-mesh-mbedtls || \
|
||||
PACKAGE_wpa-supplicant-basic || \
|
||||
PACKAGE_wpa-supplicant-mini || \
|
||||
PACKAGE_wpa-supplicant-p2p || \
|
||||
PACKAGE_wpad || \
|
||||
PACKAGE_wpad-openssl || \
|
||||
PACKAGE_wpad-wolfssl || \
|
||||
PACKAGE_wpad-mbedtls || \
|
||||
PACKAGE_wpad-basic || \
|
||||
PACKAGE_wpad-basic-openssl || \
|
||||
PACKAGE_wpad-basic-wolfssl || \
|
||||
PACKAGE_wpad-basic-mbedtls || \
|
||||
PACKAGE_wpad-mini || \
|
||||
PACKAGE_wpad-mesh-openssl || \
|
||||
PACKAGE_wpad-mesh-wolfssl || \
|
||||
PACKAGE_wpad-mesh-mbedtls
|
||||
default 3
|
||||
help
|
||||
Useful values are:
|
||||
@@ -46,7 +88,6 @@ config DRIVER_11BE_SUPPORT
|
||||
|
||||
config WPA_ENABLE_WEP
|
||||
bool "Enable support for unsecure and obsolete WEP"
|
||||
depends on PACKAGE_hostapd-common
|
||||
help
|
||||
Wired equivalent privacy (WEP) is an obsolete cryptographic data
|
||||
confidentiality algorithm that is not considered secure. It should not be used
|
||||
@@ -56,8 +97,14 @@ config WPA_ENABLE_WEP
|
||||
|
||||
config WPA_MBO_SUPPORT
|
||||
bool "Multi Band Operation (Agile Multiband)"
|
||||
depends on PACKAGE_hostapd-common
|
||||
default y
|
||||
default PACKAGE_wpa-supplicant || \
|
||||
PACKAGE_wpa-supplicant-openssl || \
|
||||
PACKAGE_wpa-supplicant-wolfssl || \
|
||||
PACKAGE_wpa-supplicant-mbedtls || \
|
||||
PACKAGE_wpad || \
|
||||
PACKAGE_wpad-openssl || \
|
||||
PACKAGE_wpad-wolfssl || \
|
||||
PACKAGE_wpad-mbedtls
|
||||
help
|
||||
Multi Band Operation aka (Agile Multiband) enables features
|
||||
that facilitate efficient use of multiple frequency bands.
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=hostapd
|
||||
PKG_RELEASE:=1
|
||||
PKG_RELEASE:=1.2
|
||||
|
||||
PKG_SOURCE_URL:=https://w1.fi/hostap.git
|
||||
PKG_SOURCE_URL:=http://w1.fi/hostap.git
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_DATE:=2025-08-26
|
||||
PKG_SOURCE_VERSION:=ca266cc24d8705eb1a2a0857ad326e48b1408b20
|
||||
PKG_MIRROR_HASH:=cccbb170ca289ad4505a399747c6503fd479ee5a6b836fa0174f727fb400d8df
|
||||
PKG_SOURCE_DATE:=2023-06-22
|
||||
PKG_SOURCE_VERSION:=599d00be9de2846c6ea18c1487d8329522ade22b
|
||||
PKG_MIRROR_HASH:=828810c558ea181e45ed0c8b940f5c41e55775e2979a15aed8cf0ab17dd7723c
|
||||
|
||||
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
||||
PKG_LICENSE:=BSD-3-Clause
|
||||
@@ -80,28 +80,21 @@ ifneq ($(CONFIG_DRIVER_11AX_SUPPORT),)
|
||||
HOSTAPD_IEEE80211AX:=y
|
||||
endif
|
||||
|
||||
ifneq ($(LOCAL_VARIANT),mini)
|
||||
ifneq ($(CONFIG_DRIVER_11BE_SUPPORT),)
|
||||
HOSTAPD_IEEE80211BE:=y
|
||||
endif
|
||||
ifneq ($(CONFIG_DRIVER_11BE_SUPPORT),)
|
||||
HOSTAPD_IEEE80211BE:=y
|
||||
endif
|
||||
|
||||
|
||||
CORE_DEPENDS = +ucode +libucode \
|
||||
+ucode-mod-fs +ucode-mod-nl80211 +ucode-mod-rtnl +ucode-mod-ubus +ucode-mod-uloop \
|
||||
+libubus +libblobmsg-json \
|
||||
+libudebug
|
||||
OPENSSL_DEPENDS = +PACKAGE_$(1):libopenssl +PACKAGE_$(1):libopenssl-legacy
|
||||
+libubus +libblobmsg-json
|
||||
|
||||
DRIVER_MAKEOPTS= \
|
||||
CONFIG_ACS=y CONFIG_DRIVER_NL80211=y \
|
||||
CONFIG_IEEE80211AC=$(HOSTAPD_IEEE80211AC) \
|
||||
CONFIG_IEEE80211AX=$(HOSTAPD_IEEE80211AX) \
|
||||
CONFIG_IEEE80211BE=$(HOSTAPD_IEEE80211BE) \
|
||||
CONFIG_MBO=$(CONFIG_WPA_MBO_SUPPORT) \
|
||||
CONFIG_UCODE=y CONFIG_APUP=y \
|
||||
$(if $(HOSTAPD_IEEE80211BE),CONFIG_OCV=y)
|
||||
|
||||
CONFIG_MBO=$(CONFIG_WPA_MBO_SUPPORT)
|
||||
|
||||
ifeq ($(SSL_VARIANT),openssl)
|
||||
DRIVER_MAKEOPTS += CONFIG_TLS=openssl CONFIG_SAE=y
|
||||
@@ -114,7 +107,7 @@ ifeq ($(SSL_VARIANT),openssl)
|
||||
DRIVER_MAKEOPTS += CONFIG_AP=y CONFIG_MESH=y
|
||||
endif
|
||||
ifeq ($(LOCAL_VARIANT),full)
|
||||
DRIVER_MAKEOPTS += CONFIG_OWE=y CONFIG_SUITEB192=y CONFIG_AP=y CONFIG_MESH=y CONFIG_EAP_PWD=y CONFIG_DPP=y CONFIG_DPP2=y
|
||||
DRIVER_MAKEOPTS += CONFIG_OWE=y CONFIG_SUITEB192=y CONFIG_AP=y CONFIG_MESH=y
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -129,7 +122,7 @@ ifeq ($(SSL_VARIANT),wolfssl)
|
||||
DRIVER_MAKEOPTS += CONFIG_AP=y CONFIG_MESH=y CONFIG_WPS_NFC=1
|
||||
endif
|
||||
ifeq ($(LOCAL_VARIANT),full)
|
||||
DRIVER_MAKEOPTS += CONFIG_OWE=y CONFIG_SUITEB192=y CONFIG_AP=y CONFIG_MESH=y CONFIG_WPS_NFC=1 CONFIG_EAP_PWD=y
|
||||
DRIVER_MAKEOPTS += CONFIG_OWE=y CONFIG_SUITEB192=y CONFIG_AP=y CONFIG_MESH=y CONFIG_WPS_NFC=1
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -144,7 +137,7 @@ ifeq ($(SSL_VARIANT),mbedtls)
|
||||
DRIVER_MAKEOPTS += CONFIG_AP=y CONFIG_MESH=y CONFIG_WPS_NFC=1
|
||||
endif
|
||||
ifeq ($(LOCAL_VARIANT),full)
|
||||
DRIVER_MAKEOPTS += CONFIG_OWE=y CONFIG_SUITEB192=y CONFIG_AP=y CONFIG_MESH=y CONFIG_WPS_NFC=1 CONFIG_EAP_PWD=y CONFIG_DPP=y CONFIG_DPP2=y
|
||||
DRIVER_MAKEOPTS += CONFIG_OWE=y CONFIG_SUITEB192=y CONFIG_AP=y CONFIG_MESH=y CONFIG_WPS_NFC=1
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -162,7 +155,7 @@ define Package/hostapd/Default
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=WirelessAPD
|
||||
TITLE:=IEEE 802.1x Authenticator
|
||||
URL:=https://w1.fi/hostapd/
|
||||
URL:=http://hostap.epitest.fi/
|
||||
DEPENDS:=$(DRV_DEPENDS) +hostapd-common $(CORE_DEPENDS)
|
||||
EXTRA_DEPENDS:=hostapd-common (=$(PKG_VERSION)-$(PKG_RELEASE))
|
||||
USERID:=network=101:network=101
|
||||
@@ -186,7 +179,7 @@ define Package/hostapd-openssl
|
||||
$(call Package/hostapd/Default,$(1))
|
||||
TITLE+= (OpenSSL full)
|
||||
VARIANT:=full-openssl
|
||||
DEPENDS+=$(OPENSSL_DEPENDS)
|
||||
DEPENDS+=+PACKAGE_hostapd-openssl:libopenssl
|
||||
endef
|
||||
|
||||
Package/hostapd-openssl/description = $(Package/hostapd/description)
|
||||
@@ -271,7 +264,7 @@ define Package/wpad/Default
|
||||
DEPENDS:=$(DRV_DEPENDS) +hostapd-common $(CORE_DEPENDS)
|
||||
EXTRA_DEPENDS:=hostapd-common (=$(PKG_VERSION)-$(PKG_RELEASE))
|
||||
USERID:=network=101:network=101
|
||||
URL:=https://w1.fi/
|
||||
URL:=http://hostap.epitest.fi/
|
||||
PROVIDES:=hostapd wpa-supplicant
|
||||
CONFLICTS:=$(HOSTAPD_PROVIDERS) $(SUPPLICANT_PROVIDERS)
|
||||
HOSTAPD_PROVIDERS+=$(1)
|
||||
@@ -293,7 +286,7 @@ define Package/wpad-openssl
|
||||
$(call Package/wpad/Default,$(1))
|
||||
TITLE+= (OpenSSL full)
|
||||
VARIANT:=wpad-full-openssl
|
||||
DEPENDS+=$(OPENSSL_DEPENDS)
|
||||
DEPENDS+=+PACKAGE_wpad-openssl:libopenssl
|
||||
endef
|
||||
|
||||
Package/wpad-openssl/description = $(Package/wpad/description)
|
||||
@@ -330,7 +323,7 @@ define Package/wpad-basic-openssl
|
||||
$(call Package/wpad/Default,$(1))
|
||||
TITLE+= (OpenSSL, 11r, 11w)
|
||||
VARIANT:=wpad-basic-openssl
|
||||
DEPENDS+=$(OPENSSL_DEPENDS)
|
||||
DEPENDS+=+PACKAGE_wpad-basic-openssl:libopenssl
|
||||
endef
|
||||
|
||||
define Package/wpad-basic-openssl/description
|
||||
@@ -382,7 +375,7 @@ endef
|
||||
define Package/wpad-mesh-openssl
|
||||
$(call Package/wpad-mesh,$(1))
|
||||
TITLE+= (OpenSSL, 11s, SAE)
|
||||
DEPENDS+=$(OPENSSL_DEPENDS)
|
||||
DEPENDS+=+PACKAGE_wpad-mesh-openssl:libopenssl
|
||||
VARIANT:=wpad-mesh-openssl
|
||||
endef
|
||||
|
||||
@@ -412,7 +405,7 @@ define Package/wpa-supplicant/Default
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=WirelessAPD
|
||||
TITLE:=WPA Supplicant
|
||||
URL:=https://w1.fi/wpa_supplicant/
|
||||
URL:=http://hostap.epitest.fi/wpa_supplicant/
|
||||
DEPENDS:=$(DRV_DEPENDS) +hostapd-common $(CORE_DEPENDS)
|
||||
EXTRA_DEPENDS:=hostapd-common (=$(PKG_VERSION)-$(PKG_RELEASE))
|
||||
USERID:=network=101:network=101
|
||||
@@ -431,7 +424,7 @@ define Package/wpa-supplicant-openssl
|
||||
$(call Package/wpa-supplicant/Default,$(1))
|
||||
TITLE+= (OpenSSL full)
|
||||
VARIANT:=supplicant-full-openssl
|
||||
DEPENDS+=$(OPENSSL_DEPENDS)
|
||||
DEPENDS+=+PACKAGE_wpa-supplicant-openssl:libopenssl
|
||||
endef
|
||||
|
||||
define Package/wpa-supplicant-wolfssl
|
||||
@@ -468,7 +461,7 @@ define Package/wpa-supplicant-mesh-openssl
|
||||
$(call Package/wpa-supplicant-mesh/Default,$(1))
|
||||
TITLE+= (OpenSSL, 11s, SAE)
|
||||
VARIANT:=supplicant-mesh-openssl
|
||||
DEPENDS+=$(OPENSSL_DEPENDS)
|
||||
DEPENDS+=+PACKAGE_wpa-supplicant-mesh-openssl:libopenssl
|
||||
endef
|
||||
|
||||
define Package/wpa-supplicant-mesh-wolfssl
|
||||
@@ -510,7 +503,7 @@ define Package/hostapd-utils
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=WirelessAPD
|
||||
TITLE:=IEEE 802.1x Authenticator (utils)
|
||||
URL:=https://w1.fi/hostapd/
|
||||
URL:=http://hostap.epitest.fi/
|
||||
DEPENDS:=@$(subst $(space),||,$(foreach pkg,$(HOSTAPD_PROVIDERS),PACKAGE_$(pkg)))
|
||||
VARIANT:=*
|
||||
endef
|
||||
@@ -548,7 +541,7 @@ define Package/eapol-test-openssl
|
||||
TITLE+= (OpenSSL full)
|
||||
VARIANT:=supplicant-full-openssl
|
||||
CONFLICTS:=$(filter-out eapol-test-openssl ,$(EAPOL_TEST_PROVIDERS))
|
||||
DEPENDS+=$(OPENSSL_DEPENDS)
|
||||
DEPENDS+=+PACKAGE_eapol-test-openssl:libopenssl
|
||||
PROVIDES:=eapol-test
|
||||
endef
|
||||
|
||||
@@ -599,7 +592,7 @@ TARGET_CPPFLAGS := \
|
||||
-D_GNU_SOURCE \
|
||||
$(if $(CONFIG_WPA_MSG_MIN_PRIORITY),-DCONFIG_MSG_MIN_PRIORITY=$(CONFIG_WPA_MSG_MIN_PRIORITY))
|
||||
|
||||
TARGET_LDFLAGS += -lubox -lubus -lblobmsg_json -lucode -lm -lnl-tiny -ludebug
|
||||
TARGET_LDFLAGS += -lubox -lubus -lblobmsg_json -lucode -lm -lnl-tiny
|
||||
|
||||
ifdef CONFIG_WPA_ENABLE_WEP
|
||||
DRIVER_MAKEOPTS += CONFIG_WEP=y
|
||||
@@ -713,25 +706,20 @@ Package/hostapd-mbedtls/conffiles = $(Package/hostapd-full/conffiles)
|
||||
endif
|
||||
|
||||
define Install/hostapd
|
||||
$(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/share/hostap
|
||||
$(INSTALL_DATA) ./files/hostapd.uc $(1)/usr/share/hostap/
|
||||
$(INSTALL_DIR) $(1)/usr/sbin
|
||||
$(if $(findstring full,$(CONFIG_VARIANT)),$(Install/hostapd/full))
|
||||
endef
|
||||
|
||||
define Install/supplicant
|
||||
$(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/share/hostap
|
||||
$(INSTALL_DATA) ./files/wpa_supplicant.uc $(1)/usr/share/hostap/
|
||||
$(INSTALL_DIR) $(1)/usr/sbin
|
||||
endef
|
||||
|
||||
define Package/hostapd-common/install
|
||||
$(INSTALL_DIR) \
|
||||
$(1)/etc/capabilities \
|
||||
$(1)/etc/hotplug.d/ieee80211 \
|
||||
$(1)/etc/init.d $(1)/lib/netifd \
|
||||
$(1)/usr/share/acl.d \
|
||||
$(1)/usr/share/hostap
|
||||
$(INSTALL_DIR) $(1)/etc/capabilities $(1)/etc/rc.button $(1)/etc/hotplug.d/ieee80211 $(1)/etc/init.d $(1)/lib/netifd $(1)/usr/share/acl.d
|
||||
$(INSTALL_BIN) ./files/dhcp-get-server.sh $(1)/lib/netifd/dhcp-get-server.sh
|
||||
$(INSTALL_DATA) ./files/hostapd.sh $(1)/lib/netifd/hostapd.sh
|
||||
$(INSTALL_BIN) ./files/wpad.init $(1)/etc/init.d/wpad
|
||||
$(INSTALL_BIN) ./files/wps-hotplug.sh $(1)/etc/rc.button/wps
|
||||
$(INSTALL_DATA) ./files/wpad_acl.json $(1)/usr/share/acl.d
|
||||
$(INSTALL_DATA) ./files/wpad.json $(1)/etc/capabilities
|
||||
endef
|
||||
|
||||
@@ -94,7 +94,7 @@ CONFIG_EAP_TTLS=y
|
||||
#CONFIG_EAP_PAX=y
|
||||
|
||||
# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
|
||||
CONFIG_EAP_PSK=y
|
||||
#CONFIG_EAP_PSK=y
|
||||
|
||||
# EAP-pwd for the integrated EAP server (secure authentication with a password)
|
||||
#CONFIG_EAP_PWD=y
|
||||
|
||||
@@ -43,37 +43,32 @@ hostapd_append_wpa_key_mgmt() {
|
||||
case "$auth_type" in
|
||||
psk|eap)
|
||||
append wpa_key_mgmt "WPA-$auth_type_l"
|
||||
[ "${wpa:-2}" -ge 2 ] && [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-${auth_type_l}"
|
||||
[ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-${auth_type_l}"
|
||||
[ "${ieee80211w:-0}" -gt 0 ] && append wpa_key_mgmt "WPA-${auth_type_l}-SHA256"
|
||||
;;
|
||||
eap192)
|
||||
append wpa_key_mgmt "WPA-EAP-SUITE-B-192"
|
||||
[ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-EAP-SHA384"
|
||||
;;
|
||||
eap-eap2)
|
||||
append wpa_key_mgmt "WPA-EAP-SHA256"
|
||||
[ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-EAP"
|
||||
[ "$rsn_override" -gt 0 ] && rsn_override_key_mgmt="$wpa_key_mgmt"
|
||||
eap-eap192)
|
||||
append wpa_key_mgmt "WPA-EAP-SUITE-B-192"
|
||||
append wpa_key_mgmt "WPA-EAP"
|
||||
;;
|
||||
eap2)
|
||||
[ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-EAP"
|
||||
append wpa_key_mgmt "WPA-EAP-SHA256"
|
||||
[ "${ieee80211r:-0}" -gt 0 ] && {
|
||||
append wpa_key_mgmt "FT-EAP-SHA384"
|
||||
append wpa_key_mgmt "FT-EAP"
|
||||
}
|
||||
[ "${ieee80211w:-0}" -gt 0 ] && append wpa_key_mgmt "WPA-EAP-SHA256"
|
||||
;;
|
||||
sae)
|
||||
append wpa_key_mgmt "SAE"
|
||||
[ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-SAE"
|
||||
;;
|
||||
psk-sae)
|
||||
append wpa_key_mgmt "WPA-PSK"
|
||||
[ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-PSK"
|
||||
[ "${ieee80211w:-0}" -gt 0 ] && append wpa_key_mgmt "WPA-PSK-SHA256"
|
||||
append wpa_key_mgmt "SAE"
|
||||
[ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-SAE"
|
||||
[ "$rsn_override" -gt 0 ] && rsn_override_key_mgmt="$wpa_key_mgmt"
|
||||
[ "$rsn_override" -gt 1 ] && wpa_key_mgmt=
|
||||
[ "$band" = "6g" ] || {
|
||||
append wpa_key_mgmt "WPA-PSK"
|
||||
[ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-PSK"
|
||||
[ "${ieee80211w:-0}" -gt 0 ] && append wpa_key_mgmt "WPA-PSK-SHA256"
|
||||
}
|
||||
;;
|
||||
owe)
|
||||
append wpa_key_mgmt "OWE"
|
||||
@@ -82,21 +77,14 @@ hostapd_append_wpa_key_mgmt() {
|
||||
|
||||
[ "$fils" -gt 0 ] && {
|
||||
case "$auth_type" in
|
||||
eap192)
|
||||
append wpa_key_mgmt FILS-SHA384
|
||||
[ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt FT-FILS-SHA384
|
||||
;;
|
||||
eap*)
|
||||
append wpa_key_mgmt FILS-SHA256
|
||||
[ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt FT-FILS-SHA256
|
||||
|
||||
[ "$rsn_override" -gt 0 ] && {
|
||||
append rsn_override_key_mgmt FILS-SHA256
|
||||
[ "${ieee80211r:-0}" -gt 0 ] && append rsn_override_key_mgmt FT-FILS-SHA256
|
||||
}
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
[ "$auth_osen" = "1" ] && append wpa_key_mgmt "OSEN"
|
||||
}
|
||||
|
||||
hostapd_add_log_config() {
|
||||
@@ -128,8 +116,7 @@ hostapd_common_add_device_config() {
|
||||
config_add_int rssi_reject_assoc_rssi
|
||||
config_add_int rssi_ignore_probe_request
|
||||
config_add_int maxassoc
|
||||
config_add_int reg_power_type
|
||||
config_add_boolean stationary_ap
|
||||
config_add_boolean vendor_vht
|
||||
|
||||
config_add_string acs_chan_bias
|
||||
config_add_array hostapd_options
|
||||
@@ -149,7 +136,7 @@ hostapd_prepare_device_config() {
|
||||
json_get_vars country country3 country_ie beacon_int:100 doth require_mode legacy_rates \
|
||||
acs_chan_bias local_pwr_constraint spectrum_mgmt_required airtime_mode cell_density \
|
||||
rts_threshold beacon_rate rssi_reject_assoc_rssi rssi_ignore_probe_request maxassoc \
|
||||
mbssid:0 band reg_power_type stationary_ap
|
||||
vendor_vht mbssid:0
|
||||
|
||||
hostapd_set_log_options base_cfg
|
||||
|
||||
@@ -218,6 +205,7 @@ hostapd_prepare_device_config() {
|
||||
set_default rate_list "24000 36000 48000 54000"
|
||||
set_default basic_rate_list "24000"
|
||||
fi
|
||||
[ -n "$vendor_vht" ] && append base_cfg "vendor_vht=$vendor_vht" "$N"
|
||||
;;
|
||||
a)
|
||||
if [ "$cell_density" -eq 1 ]; then
|
||||
@@ -252,14 +240,6 @@ hostapd_prepare_device_config() {
|
||||
[ -n "$maxassoc" ] && append base_cfg "iface_max_num_sta=$maxassoc" "$N"
|
||||
[ "$mbssid" -gt 0 ] && [ "$mbssid" -le 2 ] && append base_cfg "mbssid=$mbssid" "$N"
|
||||
|
||||
[ "$band" = "6g" ] && {
|
||||
set_default reg_power_type 0
|
||||
append base_cfg "he_6ghz_reg_pwr_type=$reg_power_type" "$N"
|
||||
}
|
||||
|
||||
set_default stationary_ap 1
|
||||
append base_cfg "stationary_ap=$stationary_ap" "$N"
|
||||
|
||||
json_get_values opts hostapd_options
|
||||
for val in $opts; do
|
||||
append base_cfg "$val" "$N"
|
||||
@@ -273,7 +253,7 @@ EOF
|
||||
|
||||
hostapd_common_add_bss_config() {
|
||||
config_add_string 'bssid:macaddr' 'ssid:string'
|
||||
config_add_boolean wds uapsd hidden utf8_ssid ppsk
|
||||
config_add_boolean wds wmm uapsd hidden utf8_ssid ppsk
|
||||
|
||||
config_add_int maxassoc max_inactivity
|
||||
config_add_boolean disassoc_low_ack isolate short_preamble skip_inactivity_poll
|
||||
@@ -343,11 +323,10 @@ hostapd_common_add_bss_config() {
|
||||
|
||||
config_add_boolean ieee80211r pmk_r1_push ft_psk_generate_local ft_over_ds
|
||||
config_add_int r0_key_lifetime reassociation_deadline
|
||||
config_add_string mobility_domain r1_key_holder rxkh_file
|
||||
config_add_string mobility_domain r1_key_holder
|
||||
config_add_array r0kh r1kh
|
||||
|
||||
config_add_int ieee80211w_max_timeout ieee80211w_retry_timeout
|
||||
config_add_int rsn_override
|
||||
|
||||
config_add_string macfilter 'macfile:file'
|
||||
config_add_array 'maclist:list(macaddr)'
|
||||
@@ -372,11 +351,14 @@ hostapd_common_add_bss_config() {
|
||||
config_add_array iw_roaming_consortium iw_domain_name iw_anqp_3gpp_cell_net iw_nai_realm
|
||||
config_add_array iw_anqp_elem iw_venue_name iw_venue_url
|
||||
|
||||
config_add_boolean hs20 disable_dgaf
|
||||
config_add_boolean hs20 disable_dgaf osen
|
||||
config_add_int anqp_domain_id
|
||||
config_add_int hs20_deauth_req_timeout
|
||||
config_add_array hs20_oper_friendly_name
|
||||
config_add_array osu_provider
|
||||
config_add_array operator_icon
|
||||
config_add_array hs20_conn_capab
|
||||
config_add_string hs20_wan_metrics hs20_operating_class hs20_t_c_filename hs20_t_c_timestamp
|
||||
config_add_string osu_ssid hs20_wan_metrics hs20_operating_class hs20_t_c_filename hs20_t_c_timestamp
|
||||
|
||||
config_add_string hs20_t_c_server_url
|
||||
|
||||
@@ -392,16 +374,13 @@ hostapd_common_add_bss_config() {
|
||||
config_add_array radius_auth_req_attr
|
||||
config_add_array radius_acct_req_attr
|
||||
|
||||
config_add_int eap_server radius_server_auth_port
|
||||
config_add_string eap_user_file ca_cert server_cert private_key private_key_passwd server_id radius_server_clients
|
||||
config_add_int eap_server
|
||||
config_add_string eap_user_file ca_cert server_cert private_key private_key_passwd server_id
|
||||
|
||||
config_add_boolean fils
|
||||
config_add_string fils_dhcp
|
||||
|
||||
config_add_int ocv
|
||||
|
||||
config_add_boolean apup
|
||||
config_add_string apup_peer_ifname_prefix
|
||||
}
|
||||
|
||||
hostapd_set_vlan_file() {
|
||||
@@ -434,36 +413,9 @@ hostapd_set_psk() {
|
||||
local ifname="$1"
|
||||
|
||||
rm -f /var/run/hostapd-${ifname}.psk
|
||||
case "$auth_type" in
|
||||
psk|psk-sae) ;;
|
||||
*) return ;;
|
||||
esac
|
||||
for_each_station hostapd_set_psk_file ${ifname}
|
||||
}
|
||||
|
||||
hostapd_set_sae_file() {
|
||||
local ifname="$1"
|
||||
local vlan="$2"
|
||||
local vlan_id=""
|
||||
|
||||
json_get_vars mac vid key
|
||||
set_default mac "ff:ff:ff:ff:ff:ff"
|
||||
[ -n "$mac" ] && mac="|mac=$mac"
|
||||
[ -n "$vid" ] && vlan_id="|vlanid=$vid"
|
||||
printf '%s%s%s\n' "${key}" "${mac}" "${vlan_id}" >> /var/run/hostapd-${ifname}.sae
|
||||
}
|
||||
|
||||
hostapd_set_sae() {
|
||||
local ifname="$1"
|
||||
|
||||
rm -f /var/run/hostapd-${ifname}.sae
|
||||
case "$auth_type" in
|
||||
sae|psk-sae) ;;
|
||||
*) return ;;
|
||||
esac
|
||||
for_each_station hostapd_set_sae_file ${ifname}
|
||||
}
|
||||
|
||||
append_iw_roaming_consortium() {
|
||||
[ -n "$1" ] && append bss_conf "roaming_consortium=$1" "$N"
|
||||
}
|
||||
@@ -480,7 +432,7 @@ append_iw_anqp_3gpp_cell_net() {
|
||||
if [ -z "$iw_anqp_3gpp_cell_net_conf" ]; then
|
||||
iw_anqp_3gpp_cell_net_conf="$1"
|
||||
else
|
||||
iw_anqp_3gpp_cell_net_conf="$iw_anqp_3gpp_cell_net_conf;$1"
|
||||
iw_anqp_3gpp_cell_net_conf="$iw_anqp_3gpp_cell_net_conf:$1"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -500,6 +452,67 @@ append_iw_venue_url() {
|
||||
append bss_conf "venue_url=$1" "$N"
|
||||
}
|
||||
|
||||
append_hs20_oper_friendly_name() {
|
||||
append bss_conf "hs20_oper_friendly_name=$1" "$N"
|
||||
}
|
||||
|
||||
append_osu_provider_friendly_name() {
|
||||
append bss_conf "osu_friendly_name=$1" "$N"
|
||||
}
|
||||
|
||||
append_osu_provider_service_desc() {
|
||||
append bss_conf "osu_service_desc=$1" "$N"
|
||||
}
|
||||
|
||||
append_hs20_icon() {
|
||||
local width height lang type path
|
||||
config_get width "$1" width
|
||||
config_get height "$1" height
|
||||
config_get lang "$1" lang
|
||||
config_get type "$1" type
|
||||
config_get path "$1" path
|
||||
|
||||
append bss_conf "hs20_icon=$width:$height:$lang:$type:$1:$path" "$N"
|
||||
}
|
||||
|
||||
append_hs20_icons() {
|
||||
config_load wireless
|
||||
config_foreach append_hs20_icon hs20-icon
|
||||
}
|
||||
|
||||
append_operator_icon() {
|
||||
append bss_conf "operator_icon=$1" "$N"
|
||||
}
|
||||
|
||||
append_osu_icon() {
|
||||
append bss_conf "osu_icon=$1" "$N"
|
||||
}
|
||||
|
||||
append_osu_provider() {
|
||||
local cfgtype osu_server_uri osu_friendly_name osu_nai osu_nai2 osu_method_list
|
||||
|
||||
config_load wireless
|
||||
config_get cfgtype "$1" TYPE
|
||||
[ "$cfgtype" != "osu-provider" ] && return
|
||||
|
||||
append bss_conf "# provider $1" "$N"
|
||||
config_get osu_server_uri "$1" osu_server_uri
|
||||
config_get osu_nai "$1" osu_nai
|
||||
config_get osu_nai2 "$1" osu_nai2
|
||||
config_get osu_method_list "$1" osu_method
|
||||
|
||||
append bss_conf "osu_server_uri=$osu_server_uri" "$N"
|
||||
append bss_conf "osu_nai=$osu_nai" "$N"
|
||||
append bss_conf "osu_nai2=$osu_nai2" "$N"
|
||||
append bss_conf "osu_method_list=$osu_method_list" "$N"
|
||||
|
||||
config_list_foreach "$1" osu_service_desc append_osu_provider_service_desc
|
||||
config_list_foreach "$1" osu_friendly_name append_osu_friendly_name
|
||||
config_list_foreach "$1" osu_icon append_osu_icon
|
||||
|
||||
append bss_conf "$N"
|
||||
}
|
||||
|
||||
append_hs20_conn_capab() {
|
||||
[ -n "$1" ] && append bss_conf "hs20_conn_capab=$1" "$N"
|
||||
}
|
||||
@@ -537,7 +550,7 @@ hostapd_set_bss_options() {
|
||||
|
||||
wireless_vif_parse_encryption
|
||||
|
||||
local bss_conf bss_md5sum ft_key rxkhs
|
||||
local bss_conf bss_md5sum ft_key
|
||||
local wep_rekey wpa_group_rekey wpa_pair_rekey wpa_master_rekey wpa_key_mgmt
|
||||
|
||||
json_get_vars \
|
||||
@@ -546,17 +559,16 @@ hostapd_set_bss_options() {
|
||||
maxassoc max_inactivity disassoc_low_ack isolate auth_cache \
|
||||
wps_pushbutton wps_label ext_registrar wps_pbc_in_m1 wps_ap_setup_locked \
|
||||
wps_independent wps_device_type wps_device_name wps_manufacturer wps_pin \
|
||||
macfilter ssid utf8_ssid uapsd hidden short_preamble rsn_preauth \
|
||||
macfilter ssid utf8_ssid wmm uapsd hidden short_preamble rsn_preauth \
|
||||
iapp_interface eapol_version dynamic_vlan ieee80211w nasid \
|
||||
acct_secret acct_port acct_interval \
|
||||
bss_load_update_period chan_util_avg_period sae_require_mfp sae_pwe \
|
||||
multi_ap multi_ap_backhaul_ssid multi_ap_backhaul_key skip_inactivity_poll \
|
||||
ppsk airtime_bss_weight airtime_bss_limit airtime_sta_weight \
|
||||
multicast_to_unicast_all proxy_arp per_sta_vif \
|
||||
eap_server eap_user_file ca_cert server_cert private_key private_key_passwd server_id radius_server_clients radius_server_auth_port \
|
||||
vendor_elements fils ocv apup rsn_override
|
||||
eap_server eap_user_file ca_cert server_cert private_key private_key_passwd server_id \
|
||||
vendor_elements fils ocv
|
||||
|
||||
set_default rsn_override 1
|
||||
set_default fils 0
|
||||
set_default isolate 0
|
||||
set_default maxassoc 0
|
||||
@@ -565,6 +577,7 @@ hostapd_set_bss_options() {
|
||||
set_default disassoc_low_ack 1
|
||||
set_default skip_inactivity_poll 0
|
||||
set_default hidden 0
|
||||
set_default wmm 1
|
||||
set_default uapsd 1
|
||||
set_default wpa_disable_eapol_key_retries 0
|
||||
set_default tdls_prohibit 0
|
||||
@@ -578,7 +591,6 @@ hostapd_set_bss_options() {
|
||||
set_default airtime_bss_weight 0
|
||||
set_default airtime_bss_limit 0
|
||||
set_default eap_server 0
|
||||
set_default apup 0
|
||||
|
||||
/usr/sbin/hostapd -vfils || fils=0
|
||||
|
||||
@@ -602,7 +614,7 @@ hostapd_set_bss_options() {
|
||||
append bss_conf "disassoc_low_ack=$disassoc_low_ack" "$N"
|
||||
append bss_conf "skip_inactivity_poll=$skip_inactivity_poll" "$N"
|
||||
append bss_conf "preamble=$short_preamble" "$N"
|
||||
append bss_conf "wmm_enabled=1" "$N"
|
||||
append bss_conf "wmm_enabled=$wmm" "$N"
|
||||
append bss_conf "ignore_broadcast_ssid=$hidden" "$N"
|
||||
append bss_conf "uapsd_advertisement_enabled=$uapsd" "$N"
|
||||
append bss_conf "utf8_ssid=$utf8_ssid" "$N"
|
||||
@@ -618,7 +630,8 @@ hostapd_set_bss_options() {
|
||||
[ -n "$wpa_strict_rekey" ] && append bss_conf "wpa_strict_rekey=$wpa_strict_rekey" "$N"
|
||||
}
|
||||
|
||||
[ -n "$nasid" ] && append bss_conf "nas_identifier=$nasid" "$N"
|
||||
set_default nasid "${macaddr//\:}"
|
||||
append bss_conf "nas_identifier=$nasid" "$N"
|
||||
|
||||
[ -n "$acct_interval" ] && \
|
||||
append bss_conf "radius_acct_interim_interval=$acct_interval" "$N"
|
||||
@@ -628,19 +641,15 @@ hostapd_set_bss_options() {
|
||||
[ -n "$ocv" ] && append bss_conf "ocv=$ocv" "$N"
|
||||
|
||||
case "$auth_type" in
|
||||
sae|owe|eap2|eap192)
|
||||
sae|owe|eap192|eap-eap192)
|
||||
set_default ieee80211w 2
|
||||
set_default sae_require_mfp 1
|
||||
[ "$ppsk" -eq 0 ] && set_default sae_pwe 2
|
||||
set_default sae_pwe 2
|
||||
;;
|
||||
psk-sae|eap-eap2)
|
||||
if [ "$band" = 6g ]; then
|
||||
set_default ieee80211w 2
|
||||
else
|
||||
set_default ieee80211w 1
|
||||
fi
|
||||
psk-sae)
|
||||
set_default ieee80211w 1
|
||||
set_default sae_require_mfp 1
|
||||
[ "$ppsk" -eq 0 ] && set_default sae_pwe 2
|
||||
set_default sae_pwe 2
|
||||
;;
|
||||
esac
|
||||
[ -n "$sae_require_mfp" ] && append bss_conf "sae_require_mfp=$sae_require_mfp" "$N"
|
||||
@@ -662,8 +671,8 @@ hostapd_set_bss_options() {
|
||||
wps_not_configured=1
|
||||
;;
|
||||
psk|sae|psk-sae)
|
||||
json_get_vars key wpa_psk_file sae_password_file
|
||||
if [ "$ppsk" -ne 0 ]; then
|
||||
json_get_vars key wpa_psk_file
|
||||
if [ "$auth_type" = "psk" ] && [ "$ppsk" -ne 0 ] ; then
|
||||
json_get_vars auth_secret auth_port
|
||||
set_default auth_port 1812
|
||||
json_for_each_item append_auth_server auth_server
|
||||
@@ -673,27 +682,22 @@ hostapd_set_bss_options() {
|
||||
append bss_conf "wpa_psk=$key" "$N"
|
||||
elif [ ${#key} -ge 8 ] && [ ${#key} -le 63 ]; then
|
||||
append bss_conf "wpa_passphrase=$key" "$N"
|
||||
elif [ -n "$key" ]; then
|
||||
elif [ -n "$key" ] || [ -z "$wpa_psk_file" ]; then
|
||||
wireless_setup_vif_failed INVALID_WPA_PSK
|
||||
return 1
|
||||
fi
|
||||
[ -z "$wpa_psk_file" ] && set_default wpa_psk_file /var/run/hostapd-$ifname.psk
|
||||
[ -n "$wpa_psk_file" ] && [ "$auth_type" = "psk" -o "$auth_type" = "psk-sae" ] && {
|
||||
[ -n "$wpa_psk_file" ] && {
|
||||
[ -e "$wpa_psk_file" ] || touch "$wpa_psk_file"
|
||||
append bss_conf "wpa_psk_file=$wpa_psk_file" "$N"
|
||||
}
|
||||
[ -z "$sae_password_file" ] && set_default sae_password_file /var/run/hostapd-$ifname.sae
|
||||
[ -n "$sae_password_file" ] && [ "$auth_type" = "sae" -o "$auth_type" = "psk-sae" ] && {
|
||||
[ -e "$sae_password_file" ] || touch "$sae_password_file"
|
||||
append bss_conf "sae_password_file=$sae_password_file" "$N"
|
||||
}
|
||||
[ "$eapol_version" -ge "1" -a "$eapol_version" -le "2" ] && append bss_conf "eapol_version=$eapol_version" "$N"
|
||||
|
||||
set_default dynamic_vlan 0
|
||||
vlan_possible=1
|
||||
wps_possible=1
|
||||
;;
|
||||
eap|eap2|eap-eap2|eap192)
|
||||
eap|eap192|eap-eap192)
|
||||
json_get_vars \
|
||||
auth_server auth_secret auth_port \
|
||||
dae_client dae_secret dae_port \
|
||||
@@ -865,9 +869,8 @@ hostapd_set_bss_options() {
|
||||
[ "$bss_transition" -eq "1" ] && append bss_conf "bss_transition=1" "$N"
|
||||
[ "$mbo" -eq 1 ] && append bss_conf "mbo=1" "$N"
|
||||
|
||||
json_get_vars ieee80211k rrm_neighbor_report rrm_beacon_report rnr
|
||||
json_get_vars ieee80211k rrm_neighbor_report rrm_beacon_report
|
||||
set_default ieee80211k 0
|
||||
set_default rnr 0
|
||||
if [ "$ieee80211k" -eq "1" ]; then
|
||||
set_default rrm_neighbor_report 1
|
||||
set_default rrm_beacon_report 1
|
||||
@@ -878,7 +881,6 @@ hostapd_set_bss_options() {
|
||||
|
||||
[ "$rrm_neighbor_report" -eq "1" ] && append bss_conf "rrm_neighbor_report=1" "$N"
|
||||
[ "$rrm_beacon_report" -eq "1" ] && append bss_conf "rrm_beacon_report=1" "$N"
|
||||
[ "$rnr" -eq "1" ] && append bss_conf "rnr=1" "$N"
|
||||
|
||||
json_get_vars ftm_responder stationary_ap lci civic
|
||||
set_default ftm_responder 0
|
||||
@@ -892,26 +894,10 @@ hostapd_set_bss_options() {
|
||||
}
|
||||
fi
|
||||
|
||||
json_get_vars ieee80211r
|
||||
set_default ieee80211r 0
|
||||
if [ "$wpa" -ge "1" ]; then
|
||||
if [ "$fils" -gt 0 ]; then
|
||||
json_get_vars fils_realm
|
||||
set_default fils_realm "$(echo "$ssid" | md5sum | head -c 8)"
|
||||
fi
|
||||
json_get_vars ieee80211r
|
||||
set_default ieee80211r 0
|
||||
|
||||
append bss_conf "wpa_disable_eapol_key_retries=$wpa_disable_eapol_key_retries" "$N"
|
||||
|
||||
hostapd_append_wpa_key_mgmt
|
||||
[ -n "$wpa_key_mgmt" ] && append bss_conf "wpa_key_mgmt=$wpa_key_mgmt" "$N"
|
||||
[ -n "$rsn_override_key_mgmt" -o -n "$rsn_override_pairwise" ] && {
|
||||
append bss_conf "rsn_override_key_mgmt=${rsn_override_key_mgmt:-$wpa_key_mgmt}" "$N"
|
||||
append bss_conf "rsn_override_pairwise=${rsn_override_pairwise:-$wpa_pairwise}" "$N"
|
||||
append bss_conf "rsn_override_mfp=$ieee80211w" "$N"
|
||||
}
|
||||
fi
|
||||
|
||||
if [ "$wpa" -ge "2" ]; then
|
||||
if [ "$ieee80211r" -gt "0" ]; then
|
||||
json_get_vars mobility_domain ft_psk_generate_local ft_over_ds reassociation_deadline
|
||||
|
||||
@@ -920,7 +906,7 @@ hostapd_set_bss_options() {
|
||||
set_default reassociation_deadline 1000
|
||||
|
||||
case "$auth_type" in
|
||||
psk)
|
||||
psk|sae|psk-sae)
|
||||
set_default ft_psk_generate_local 1
|
||||
;;
|
||||
*)
|
||||
@@ -935,7 +921,7 @@ hostapd_set_bss_options() {
|
||||
append bss_conf "reassociation_deadline=$reassociation_deadline" "$N"
|
||||
|
||||
if [ "$ft_psk_generate_local" -eq "0" ]; then
|
||||
json_get_vars r0_key_lifetime r1_key_holder pmk_r1_push rxkh_file
|
||||
json_get_vars r0_key_lifetime r1_key_holder pmk_r1_push
|
||||
json_get_values r0kh r0kh
|
||||
json_get_values r1kh r1kh
|
||||
|
||||
@@ -943,10 +929,6 @@ hostapd_set_bss_options() {
|
||||
set_default pmk_r1_push 0
|
||||
|
||||
[ -n "$r0kh" -a -n "$r1kh" ] || {
|
||||
if [ -z "$auth_secret" -a -z "$key" ]; then
|
||||
wireless_setup_vif_failed FT_KEY_CANT_BE_DERIVED
|
||||
return 1
|
||||
fi
|
||||
ft_key=`echo -n "$mobility_domain/${auth_secret:-${key}}" | md5sum | awk '{print $1}'`
|
||||
|
||||
set_default r0kh "ff:ff:ff:ff:ff:ff,*,$ft_key"
|
||||
@@ -957,23 +939,26 @@ hostapd_set_bss_options() {
|
||||
append bss_conf "r0_key_lifetime=$r0_key_lifetime" "$N"
|
||||
append bss_conf "pmk_r1_push=$pmk_r1_push" "$N"
|
||||
|
||||
if [ -z "$rxkh_file" ]; then
|
||||
set_default rxkh_file /var/run/hostapd-$ifname.rxkh
|
||||
[ -e "$rxkh_file" ] && rm -f "$rxkh_file"
|
||||
touch "$rxkh_file"
|
||||
|
||||
for kh in $r0kh; do
|
||||
append rxkhs "r0kh=${kh//,/ }" "$N"
|
||||
done
|
||||
for kh in $r1kh; do
|
||||
append rxkhs "r1kh=${kh//,/ }" "$N"
|
||||
done
|
||||
echo "$rxkhs" > "$rxkh_file"
|
||||
fi
|
||||
append bss_conf "rxkh_file=$rxkh_file" "$N"
|
||||
for kh in $r0kh; do
|
||||
append bss_conf "r0kh=${kh//,/ }" "$N"
|
||||
done
|
||||
for kh in $r1kh; do
|
||||
append bss_conf "r1kh=${kh//,/ }" "$N"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
if [ "$fils" -gt 0 ]; then
|
||||
json_get_vars fils_realm
|
||||
set_default fils_realm "$(echo "$ssid" | md5sum | head -c 8)"
|
||||
fi
|
||||
|
||||
append bss_conf "wpa_disable_eapol_key_retries=$wpa_disable_eapol_key_retries" "$N"
|
||||
|
||||
hostapd_append_wpa_key_mgmt
|
||||
[ -n "$wpa_key_mgmt" ] && append bss_conf "wpa_key_mgmt=$wpa_key_mgmt" "$N"
|
||||
fi
|
||||
|
||||
if [ "$wpa" -ge "2" ]; then
|
||||
if [ -n "$network_bridge" -a "$rsn_preauth" = 1 ]; then
|
||||
set_default auth_cache 1
|
||||
append bss_conf "rsn_preauth=1" "$N"
|
||||
@@ -1115,28 +1100,35 @@ hostapd_set_bss_options() {
|
||||
esac
|
||||
[ -n "$iw_qos_map_set" ] && append bss_conf "qos_map_set=$iw_qos_map_set" "$N"
|
||||
|
||||
local hs20 disable_dgaf anqp_domain_id hs20_deauth_req_timeout \
|
||||
hs20_wan_metrics hs20_operating_class hs20_t_c_filename hs20_t_c_timestamp \
|
||||
local hs20 disable_dgaf osen anqp_domain_id hs20_deauth_req_timeout \
|
||||
osu_ssid hs20_wan_metrics hs20_operating_class hs20_t_c_filename hs20_t_c_timestamp \
|
||||
hs20_t_c_server_url
|
||||
json_get_vars hs20 disable_dgaf anqp_domain_id hs20_deauth_req_timeout \
|
||||
hs20_wan_metrics hs20_operating_class hs20_t_c_filename hs20_t_c_timestamp \
|
||||
json_get_vars hs20 disable_dgaf osen anqp_domain_id hs20_deauth_req_timeout \
|
||||
osu_ssid hs20_wan_metrics hs20_operating_class hs20_t_c_filename hs20_t_c_timestamp \
|
||||
hs20_t_c_server_url
|
||||
|
||||
set_default hs20 0
|
||||
set_default disable_dgaf $hs20
|
||||
set_default osen 0
|
||||
set_default anqp_domain_id 0
|
||||
set_default hs20_deauth_req_timeout 60
|
||||
if [ "$hs20" = "1" ]; then
|
||||
append bss_conf "hs20=1" "$N"
|
||||
append_hs20_icons
|
||||
append bss_conf "disable_dgaf=$disable_dgaf" "$N"
|
||||
append bss_conf "osen=$osen" "$N"
|
||||
append bss_conf "anqp_domain_id=$anqp_domain_id" "$N"
|
||||
append bss_conf "hs20_deauth_req_timeout=$hs20_deauth_req_timeout" "$N"
|
||||
[ -n "$osu_ssid" ] && append bss_conf "osu_ssid=$osu_ssid" "$N"
|
||||
[ -n "$hs20_wan_metrics" ] && append bss_conf "hs20_wan_metrics=$hs20_wan_metrics" "$N"
|
||||
[ -n "$hs20_operating_class" ] && append bss_conf "hs20_operating_class=$hs20_operating_class" "$N"
|
||||
[ -n "$hs20_t_c_filename" ] && append bss_conf "hs20_t_c_filename=$hs20_t_c_filename" "$N"
|
||||
[ -n "$hs20_t_c_timestamp" ] && append bss_conf "hs20_t_c_timestamp=$hs20_t_c_timestamp" "$N"
|
||||
[ -n "$hs20_t_c_server_url" ] && append bss_conf "hs20_t_c_server_url=$hs20_t_c_server_url" "$N"
|
||||
json_for_each_item append_hs20_oper_friendly_name hs20_oper_friendly_name
|
||||
json_for_each_item append_hs20_conn_capab hs20_conn_capab
|
||||
json_for_each_item append_osu_provider osu_provider
|
||||
json_for_each_item append_operator_icon operator_icon
|
||||
fi
|
||||
|
||||
if [ "$eap_server" = "1" ]; then
|
||||
@@ -1148,8 +1140,6 @@ hostapd_set_bss_options() {
|
||||
[ -n "$private_key" ] && append bss_conf "private_key=$private_key" "$N"
|
||||
[ -n "$private_key_passwd" ] && append bss_conf "private_key_passwd=$private_key_passwd" "$N"
|
||||
[ -n "$server_id" ] && append bss_conf "server_id=$server_id" "$N"
|
||||
[ -n "$radius_server_clients" ] && append bss_conf "radius_server_clients=$radius_server_clients" "$N"
|
||||
[ -n "$radius_server_auth_port" ] && append bss_conf "radius_server_auth_port=$radius_server_auth_port" "$N"
|
||||
fi
|
||||
|
||||
set_default multicast_to_unicast_all 0
|
||||
@@ -1166,21 +1156,14 @@ hostapd_set_bss_options() {
|
||||
append bss_conf "per_sta_vif=$per_sta_vif" "$N"
|
||||
fi
|
||||
|
||||
if [ "$apup" -gt 0 ]; then
|
||||
append bss_conf "apup=$apup" "$N"
|
||||
|
||||
local apup_peer_ifname_prefix
|
||||
json_get_vars apup_peer_ifname_prefix
|
||||
if [ -n "$apup_peer_ifname_prefix" ] ; then
|
||||
append bss_conf "apup_peer_ifname_prefix=$apup_peer_ifname_prefix" "$N"
|
||||
fi
|
||||
fi
|
||||
|
||||
json_get_values opts hostapd_bss_options
|
||||
for val in $opts; do
|
||||
append bss_conf "$val" "$N"
|
||||
done
|
||||
|
||||
bss_md5sum="$(echo $bss_conf | md5sum | cut -d" " -f1)"
|
||||
append bss_conf "config_id=$bss_md5sum" "$N"
|
||||
|
||||
append "$var" "$bss_conf" "$N"
|
||||
return 0
|
||||
}
|
||||
@@ -1315,18 +1298,14 @@ wpa_supplicant_add_network() {
|
||||
wireless_vif_parse_encryption
|
||||
|
||||
json_get_vars \
|
||||
ssid bssid key rsn_override \
|
||||
mcast_rate \
|
||||
ssid bssid key \
|
||||
basic_rate mcast_rate \
|
||||
ieee80211w ieee80211r fils ocv \
|
||||
multi_ap \
|
||||
default_disabled
|
||||
|
||||
json_get_values basic_rate_list basic_rate
|
||||
|
||||
set_default rsn_override 1
|
||||
|
||||
case "$auth_type" in
|
||||
sae|owe|eap2|eap192)
|
||||
sae|owe|eap192|eap-eap192)
|
||||
set_default ieee80211w 2
|
||||
;;
|
||||
psk-sae)
|
||||
@@ -1336,7 +1315,6 @@ wpa_supplicant_add_network() {
|
||||
|
||||
set_default ieee80211r 0
|
||||
set_default multi_ap 0
|
||||
set_default sae_pwe 2
|
||||
set_default default_disabled 0
|
||||
|
||||
local key_mgmt='NONE'
|
||||
@@ -1376,12 +1354,6 @@ wpa_supplicant_add_network() {
|
||||
|
||||
[ -n "$ocv" ] && append network_data "ocv=$ocv" "$N$T"
|
||||
|
||||
rsn_overriding=0
|
||||
case "$htmode" in
|
||||
EHT*|HE*) [ "$rsn_override" -gt 0 ] && rsn_overriding=1;;
|
||||
esac
|
||||
append network_data "rsn_overriding=$rsn_overriding" "$N$T"
|
||||
|
||||
case "$auth_type" in
|
||||
none) ;;
|
||||
owe)
|
||||
@@ -1416,7 +1388,7 @@ wpa_supplicant_add_network() {
|
||||
fi
|
||||
append network_data "$passphrase" "$N$T"
|
||||
;;
|
||||
eap|eap2|eap192)
|
||||
eap|eap192|eap-eap192)
|
||||
hostapd_append_wpa_key_mgmt
|
||||
key_mgmt="$wpa_key_mgmt"
|
||||
|
||||
@@ -1592,21 +1564,12 @@ wpa_supplicant_add_network() {
|
||||
[ -n "$bssid_blacklist" ] && append network_data "bssid_blacklist=$bssid_blacklist" "$N$T"
|
||||
[ -n "$bssid_whitelist" ] && append network_data "bssid_whitelist=$bssid_whitelist" "$N$T"
|
||||
|
||||
[ -n "$basic_rate_list" ] && {
|
||||
local br rate rate_list=
|
||||
|
||||
if [ "$mode" = mesh ]; then
|
||||
for br in $basic_rate_list; do
|
||||
rate="$(($br / 100))"
|
||||
append rate_list "$rate" " "
|
||||
done
|
||||
[ -n "$rate_list" ] && append network_data "mesh_basic_rates=$rate_list" "$N$T"
|
||||
else
|
||||
for br in $basic_rate_list; do
|
||||
wpa_supplicant_add_rate rate_list "$br"
|
||||
done
|
||||
[ -n "$rate_list" ] && append network_data "rates=$rate_list" "$N$T"
|
||||
fi
|
||||
[ -n "$basic_rate" ] && {
|
||||
local br rate_list=
|
||||
for br in $basic_rate; do
|
||||
wpa_supplicant_add_rate rate_list "$br"
|
||||
done
|
||||
[ -n "$rate_list" ] && append network_data "rates=$rate_list" "$N$T"
|
||||
}
|
||||
|
||||
[ -n "$mcast_rate" ] && {
|
||||
@@ -1623,10 +1586,36 @@ network={
|
||||
$scan_ssid
|
||||
ssid="$ssid"
|
||||
key_mgmt=$key_mgmt
|
||||
sae_pwe=$sae_pwe
|
||||
$network_data
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
wpa_supplicant_run() {
|
||||
local ifname="$1"
|
||||
local hostapd_ctrl="$2"
|
||||
|
||||
_wpa_supplicant_common "$ifname"
|
||||
|
||||
ubus wait_for wpa_supplicant
|
||||
local supplicant_res="$(ubus call wpa_supplicant config_add "{ \
|
||||
\"driver\": \"${_w_driver:-wext}\", \"ctrl\": \"$_rpath\", \
|
||||
\"iface\": \"$ifname\", \"config\": \"$_config\" \
|
||||
${network_bridge:+, \"bridge\": \"$network_bridge\"} \
|
||||
${hostapd_ctrl:+, \"hostapd_ctrl\": \"$hostapd_ctrl\"} \
|
||||
}")"
|
||||
|
||||
ret="$?"
|
||||
|
||||
[ "$ret" != 0 -o -z "$supplicant_res" ] && wireless_setup_vif_failed WPA_SUPPLICANT_FAILED
|
||||
|
||||
wireless_add_process "$(jsonfilter -s "$supplicant_res" -l 1 -e @.pid)" "/usr/sbin/wpa_supplicant" 1 1
|
||||
|
||||
return $ret
|
||||
}
|
||||
|
||||
hostapd_common_cleanup() {
|
||||
killall meshd-nl80211
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,17 +1,5 @@
|
||||
config radius
|
||||
option disabled '1'
|
||||
option ipv6 '1'
|
||||
|
||||
# Logging levels:
|
||||
# 0: ALL
|
||||
# 1: MSGDUMP
|
||||
# 2: DEBUG
|
||||
# 3: INFO
|
||||
# 4: WARNING
|
||||
# 5: ERROR
|
||||
# Default: INFO
|
||||
option log_level '3'
|
||||
|
||||
option ca_cert '/etc/radius/ca.pem'
|
||||
option cert '/etc/radius/cert.pem'
|
||||
option key '/etc/radius/key.pem'
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user