link.go 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. //go:build linux
  2. package bridge
  3. import (
  4. "context"
  5. "fmt"
  6. "net"
  7. "github.com/containerd/log"
  8. "github.com/docker/docker/libnetwork/iptables"
  9. "github.com/docker/docker/libnetwork/types"
  10. )
  11. type link struct {
  12. parentIP net.IP
  13. childIP net.IP
  14. ports []types.TransportPort
  15. bridge string
  16. }
  17. func (l *link) String() string {
  18. return fmt.Sprintf("%s <-> %s [%v] on %s", l.parentIP, l.childIP, l.ports, l.bridge)
  19. }
  20. func newLink(parentIP, childIP net.IP, ports []types.TransportPort, bridge string) (*link, error) {
  21. if parentIP == nil {
  22. return nil, fmt.Errorf("cannot link to a container with an empty parent IP address")
  23. }
  24. if childIP == nil {
  25. return nil, fmt.Errorf("cannot link to a container with an empty child IP address")
  26. }
  27. return &link{
  28. childIP: childIP,
  29. parentIP: parentIP,
  30. ports: ports,
  31. bridge: bridge,
  32. }, nil
  33. }
  34. func (l *link) Enable() error {
  35. linkFunction := func() error {
  36. return linkContainers(iptables.Append, l.parentIP, l.childIP, l.ports, l.bridge, false)
  37. }
  38. if err := linkFunction(); err != nil {
  39. return err
  40. }
  41. iptables.OnReloaded(func() { _ = linkFunction() })
  42. return nil
  43. }
  44. func (l *link) Disable() {
  45. if err := linkContainers(iptables.Delete, l.parentIP, l.childIP, l.ports, l.bridge, true); err != nil {
  46. // @TODO: Return error once we have the iptables package return typed errors.
  47. log.G(context.TODO()).WithError(err).Errorf("Error removing IPTables rules for link: %s", l.String())
  48. }
  49. }
  50. func linkContainers(action iptables.Action, parentIP, childIP net.IP, ports []types.TransportPort, bridge string, ignoreErrors bool) error {
  51. if parentIP == nil {
  52. return fmt.Errorf("cannot link to a container with an empty parent IP address")
  53. }
  54. if childIP == nil {
  55. return fmt.Errorf("cannot link to a container with an empty child IP address")
  56. }
  57. chain := iptables.ChainInfo{Name: DockerChain}
  58. for _, port := range ports {
  59. err := chain.Link(action, parentIP, childIP, int(port.Port), port.Proto.String(), bridge)
  60. if !ignoreErrors && err != nil {
  61. return err
  62. }
  63. }
  64. return nil
  65. }