link.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. package bridge
  2. import (
  3. "fmt"
  4. "net"
  5. "github.com/Sirupsen/logrus"
  6. "github.com/docker/libnetwork/iptables"
  7. "github.com/docker/libnetwork/types"
  8. )
  9. type link struct {
  10. parentIP string
  11. childIP string
  12. ports []types.TransportPort
  13. bridge string
  14. }
  15. func (l *link) String() string {
  16. return fmt.Sprintf("%s <-> %s [%v] on %s", l.parentIP, l.childIP, l.ports, l.bridge)
  17. }
  18. func newLink(parentIP, childIP string, ports []types.TransportPort, bridge string) *link {
  19. return &link{
  20. childIP: childIP,
  21. parentIP: parentIP,
  22. ports: ports,
  23. bridge: bridge,
  24. }
  25. }
  26. func (l *link) Enable() error {
  27. // -A == iptables append flag
  28. linkFunction := func() error {
  29. return linkContainers("-A", l.parentIP, l.childIP, l.ports, l.bridge, false)
  30. }
  31. iptables.OnReloaded(func() { linkFunction() })
  32. return linkFunction()
  33. }
  34. func (l *link) Disable() {
  35. // -D == iptables delete flag
  36. err := linkContainers("-D", l.parentIP, l.childIP, l.ports, l.bridge, true)
  37. if err != nil {
  38. logrus.Errorf("Error removing IPTables rules for a link %s due to %s", l.String(), err.Error())
  39. }
  40. // Return proper error once we move to use a proper iptables package
  41. // that returns typed errors
  42. }
  43. func linkContainers(action, parentIP, childIP string, ports []types.TransportPort, bridge string,
  44. ignoreErrors bool) error {
  45. var nfAction iptables.Action
  46. switch action {
  47. case "-A":
  48. nfAction = iptables.Append
  49. case "-I":
  50. nfAction = iptables.Insert
  51. case "-D":
  52. nfAction = iptables.Delete
  53. default:
  54. return InvalidIPTablesCfgError(action)
  55. }
  56. ip1 := net.ParseIP(parentIP)
  57. if ip1 == nil {
  58. return InvalidLinkIPAddrError(parentIP)
  59. }
  60. ip2 := net.ParseIP(childIP)
  61. if ip2 == nil {
  62. return InvalidLinkIPAddrError(childIP)
  63. }
  64. chain := iptables.ChainInfo{Name: DockerChain}
  65. for _, port := range ports {
  66. err := chain.Link(nfAction, ip1, ip2, int(port.Port), port.Proto.String(), bridge)
  67. if !ignoreErrors && err != nil {
  68. return err
  69. }
  70. }
  71. return nil
  72. }