github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/libnetwork/iptables/firewalld.go (about) 1 package iptables 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/Sirupsen/logrus" 8 "github.com/godbus/dbus" 9 ) 10 11 // IPV defines the table string 12 type IPV string 13 14 const ( 15 // Iptables point ipv4 table 16 Iptables IPV = "ipv4" 17 // IP6Tables point to ipv6 table 18 IP6Tables IPV = "ipv6" 19 // Ebtables point to bridge table 20 Ebtables IPV = "eb" 21 ) 22 const ( 23 dbusInterface = "org.fedoraproject.FirewallD1" 24 dbusPath = "/org/fedoraproject/FirewallD1" 25 ) 26 27 // Conn is a connection to firewalld dbus endpoint. 28 type Conn struct { 29 sysconn *dbus.Conn 30 sysobj dbus.BusObject 31 signal chan *dbus.Signal 32 } 33 34 var ( 35 connection *Conn 36 firewalldRunning bool // is Firewalld service running 37 onReloaded []*func() // callbacks when Firewalld has been reloaded 38 ) 39 40 // FirewalldInit initializes firewalld management code. 41 func FirewalldInit() error { 42 var err error 43 44 if connection, err = newConnection(); err != nil { 45 return fmt.Errorf("Failed to connect to D-Bus system bus: %v", err) 46 } 47 firewalldRunning = checkRunning() 48 if !firewalldRunning { 49 connection.sysconn.Close() 50 connection = nil 51 } 52 if connection != nil { 53 go signalHandler() 54 } 55 56 return nil 57 } 58 59 // New() establishes a connection to the system bus. 60 func newConnection() (*Conn, error) { 61 c := new(Conn) 62 if err := c.initConnection(); err != nil { 63 return nil, err 64 } 65 66 return c, nil 67 } 68 69 // Innitialize D-Bus connection. 70 func (c *Conn) initConnection() error { 71 var err error 72 73 c.sysconn, err = dbus.SystemBus() 74 if err != nil { 75 return err 76 } 77 78 // This never fails, even if the service is not running atm. 79 c.sysobj = c.sysconn.Object(dbusInterface, dbus.ObjectPath(dbusPath)) 80 81 rule := fmt.Sprintf("type='signal',path='%s',interface='%s',sender='%s',member='Reloaded'", 82 dbusPath, dbusInterface, dbusInterface) 83 c.sysconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, rule) 84 85 rule = fmt.Sprintf("type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged',path='/org/freedesktop/DBus',sender='org.freedesktop.DBus',arg0='%s'", 86 dbusInterface) 87 c.sysconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, rule) 88 89 c.signal = make(chan *dbus.Signal, 10) 90 c.sysconn.Signal(c.signal) 91 92 return nil 93 } 94 95 func signalHandler() { 96 for signal := range connection.signal { 97 if strings.Contains(signal.Name, "NameOwnerChanged") { 98 firewalldRunning = checkRunning() 99 dbusConnectionChanged(signal.Body) 100 } else if strings.Contains(signal.Name, "Reloaded") { 101 reloaded() 102 } 103 } 104 } 105 106 func dbusConnectionChanged(args []interface{}) { 107 name := args[0].(string) 108 oldOwner := args[1].(string) 109 newOwner := args[2].(string) 110 111 if name != dbusInterface { 112 return 113 } 114 115 if len(newOwner) > 0 { 116 connectionEstablished() 117 } else if len(oldOwner) > 0 { 118 connectionLost() 119 } 120 } 121 122 func connectionEstablished() { 123 reloaded() 124 } 125 126 func connectionLost() { 127 // Doesn't do anything for now. Libvirt also doesn't react to this. 128 } 129 130 // call all callbacks 131 func reloaded() { 132 for _, pf := range onReloaded { 133 (*pf)() 134 } 135 } 136 137 // OnReloaded add callback 138 func OnReloaded(callback func()) { 139 for _, pf := range onReloaded { 140 if pf == &callback { 141 return 142 } 143 } 144 onReloaded = append(onReloaded, &callback) 145 } 146 147 // Call some remote method to see whether the service is actually running. 148 func checkRunning() bool { 149 var zone string 150 var err error 151 152 if connection != nil { 153 err = connection.sysobj.Call(dbusInterface+".getDefaultZone", 0).Store(&zone) 154 logrus.Infof("Firewalld running: %t", err == nil) 155 return err == nil 156 } 157 return false 158 } 159 160 // Passthrough method simply passes args through to iptables/ip6tables 161 func Passthrough(ipv IPV, args ...string) ([]byte, error) { 162 var output string 163 logrus.Debugf("Firewalld passthrough: %s, %s", ipv, args) 164 if err := connection.sysobj.Call(dbusInterface+".direct.passthrough", 0, ipv, args).Store(&output); err != nil { 165 return nil, err 166 } 167 return []byte(output), nil 168 }