github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/libnetwork/types/types.go (about) 1 // Package types contains types that are common across libnetwork project 2 package types 3 4 import ( 5 "bytes" 6 "fmt" 7 "net" 8 "strconv" 9 "strings" 10 11 "github.com/ishidawataru/sctp" 12 ) 13 14 // constants for the IP address type 15 const ( 16 IP = iota // IPv4 and IPv6 17 IPv4 18 IPv6 19 ) 20 21 // EncryptionKey is the libnetwork representation of the key distributed by the lead 22 // manager. 23 type EncryptionKey struct { 24 Subsystem string 25 Algorithm int32 26 Key []byte 27 LamportTime uint64 28 } 29 30 // UUID represents a globally unique ID of various resources like network and endpoint 31 type UUID string 32 33 // QosPolicy represents a quality of service policy on an endpoint 34 type QosPolicy struct { 35 MaxEgressBandwidth uint64 36 } 37 38 // TransportPort represents a local Layer 4 endpoint 39 type TransportPort struct { 40 Proto Protocol 41 Port uint16 42 } 43 44 // Equal checks if this instance of Transportport is equal to the passed one 45 func (t *TransportPort) Equal(o *TransportPort) bool { 46 if t == o { 47 return true 48 } 49 50 if o == nil { 51 return false 52 } 53 54 if t.Proto != o.Proto || t.Port != o.Port { 55 return false 56 } 57 58 return true 59 } 60 61 // GetCopy returns a copy of this TransportPort structure instance 62 func (t *TransportPort) GetCopy() TransportPort { 63 return TransportPort{Proto: t.Proto, Port: t.Port} 64 } 65 66 // String returns the TransportPort structure in string form 67 func (t *TransportPort) String() string { 68 return fmt.Sprintf("%s/%d", t.Proto.String(), t.Port) 69 } 70 71 // FromString reads the TransportPort structure from string 72 func (t *TransportPort) FromString(s string) error { 73 ps := strings.Split(s, "/") 74 if len(ps) == 2 { 75 t.Proto = ParseProtocol(ps[0]) 76 if p, err := strconv.ParseUint(ps[1], 10, 16); err == nil { 77 t.Port = uint16(p) 78 return nil 79 } 80 } 81 return BadRequestErrorf("invalid format for transport port: %s", s) 82 } 83 84 // PortBinding represents a port binding between the container and the host 85 type PortBinding struct { 86 Proto Protocol 87 IP net.IP 88 Port uint16 89 HostIP net.IP 90 HostPort uint16 91 HostPortEnd uint16 92 } 93 94 // HostAddr returns the host side transport address 95 func (p PortBinding) HostAddr() (net.Addr, error) { 96 switch p.Proto { 97 case UDP: 98 return &net.UDPAddr{IP: p.HostIP, Port: int(p.HostPort)}, nil 99 case TCP: 100 return &net.TCPAddr{IP: p.HostIP, Port: int(p.HostPort)}, nil 101 case SCTP: 102 return &sctp.SCTPAddr{IPAddrs: []net.IPAddr{{IP: p.HostIP}}, Port: int(p.HostPort)}, nil 103 default: 104 return nil, ErrInvalidProtocolBinding(p.Proto.String()) 105 } 106 } 107 108 // ContainerAddr returns the container side transport address 109 func (p PortBinding) ContainerAddr() (net.Addr, error) { 110 switch p.Proto { 111 case UDP: 112 return &net.UDPAddr{IP: p.IP, Port: int(p.Port)}, nil 113 case TCP: 114 return &net.TCPAddr{IP: p.IP, Port: int(p.Port)}, nil 115 case SCTP: 116 return &sctp.SCTPAddr{IPAddrs: []net.IPAddr{{IP: p.IP}}, Port: int(p.Port)}, nil 117 default: 118 return nil, ErrInvalidProtocolBinding(p.Proto.String()) 119 } 120 } 121 122 // GetCopy returns a copy of this PortBinding structure instance 123 func (p *PortBinding) GetCopy() PortBinding { 124 return PortBinding{ 125 Proto: p.Proto, 126 IP: GetIPCopy(p.IP), 127 Port: p.Port, 128 HostIP: GetIPCopy(p.HostIP), 129 HostPort: p.HostPort, 130 HostPortEnd: p.HostPortEnd, 131 } 132 } 133 134 // String returns the PortBinding structure in string form 135 func (p *PortBinding) String() string { 136 ret := fmt.Sprintf("%s/", p.Proto) 137 if p.IP != nil { 138 ret += p.IP.String() 139 } 140 ret = fmt.Sprintf("%s:%d/", ret, p.Port) 141 if p.HostIP != nil { 142 ret += p.HostIP.String() 143 } 144 ret = fmt.Sprintf("%s:%d", ret, p.HostPort) 145 return ret 146 } 147 148 // FromString reads the PortBinding structure from string s. 149 // String s is a triple of "protocol/containerIP:port/hostIP:port" 150 // containerIP and hostIP can be in dotted decimal ("192.0.2.1") or IPv6 ("2001:db8::68") form. 151 // Zoned addresses ("169.254.0.23%eth0" or "fe80::1ff:fe23:4567:890a%eth0") are not supported. 152 // If string s is incorrectly formatted or the IP addresses or ports cannot be parsed, FromString 153 // returns an error. 154 func (p *PortBinding) FromString(s string) error { 155 ps := strings.Split(s, "/") 156 if len(ps) != 3 { 157 return BadRequestErrorf("invalid format for port binding: %s", s) 158 } 159 160 p.Proto = ParseProtocol(ps[0]) 161 162 var err error 163 if p.IP, p.Port, err = parseIPPort(ps[1]); err != nil { 164 return BadRequestErrorf("failed to parse Container IP/Port in port binding: %s", err.Error()) 165 } 166 167 if p.HostIP, p.HostPort, err = parseIPPort(ps[2]); err != nil { 168 return BadRequestErrorf("failed to parse Host IP/Port in port binding: %s", err.Error()) 169 } 170 171 return nil 172 } 173 174 func parseIPPort(s string) (net.IP, uint16, error) { 175 hoststr, portstr, err := net.SplitHostPort(s) 176 if err != nil { 177 return nil, 0, err 178 } 179 180 ip := net.ParseIP(hoststr) 181 if ip == nil { 182 return nil, 0, BadRequestErrorf("invalid ip: %s", hoststr) 183 } 184 185 port, err := strconv.ParseUint(portstr, 10, 16) 186 if err != nil { 187 return nil, 0, BadRequestErrorf("invalid port: %s", portstr) 188 } 189 190 return ip, uint16(port), nil 191 } 192 193 // Equal checks if this instance of PortBinding is equal to the passed one 194 func (p *PortBinding) Equal(o *PortBinding) bool { 195 if p == o { 196 return true 197 } 198 199 if o == nil { 200 return false 201 } 202 203 if p.Proto != o.Proto || p.Port != o.Port || 204 p.HostPort != o.HostPort || p.HostPortEnd != o.HostPortEnd { 205 return false 206 } 207 208 if p.IP != nil { 209 if !p.IP.Equal(o.IP) { 210 return false 211 } 212 } else { 213 if o.IP != nil { 214 return false 215 } 216 } 217 218 if p.HostIP != nil { 219 if !p.HostIP.Equal(o.HostIP) { 220 return false 221 } 222 } else { 223 if o.HostIP != nil { 224 return false 225 } 226 } 227 228 return true 229 } 230 231 // ErrInvalidProtocolBinding is returned when the port binding protocol is not valid. 232 type ErrInvalidProtocolBinding string 233 234 func (ipb ErrInvalidProtocolBinding) Error() string { 235 return fmt.Sprintf("invalid transport protocol: %s", string(ipb)) 236 } 237 238 const ( 239 // ICMP is for the ICMP ip protocol 240 ICMP = 1 241 // TCP is for the TCP ip protocol 242 TCP = 6 243 // UDP is for the UDP ip protocol 244 UDP = 17 245 // SCTP is for the SCTP ip protocol 246 SCTP = 132 247 ) 248 249 // Protocol represents an IP protocol number 250 type Protocol uint8 251 252 func (p Protocol) String() string { 253 switch p { 254 case ICMP: 255 return "icmp" 256 case TCP: 257 return "tcp" 258 case UDP: 259 return "udp" 260 case SCTP: 261 return "sctp" 262 default: 263 return fmt.Sprintf("%d", p) 264 } 265 } 266 267 // ParseProtocol returns the respective Protocol type for the passed string 268 func ParseProtocol(s string) Protocol { 269 switch strings.ToLower(s) { 270 case "icmp": 271 return ICMP 272 case "udp": 273 return UDP 274 case "tcp": 275 return TCP 276 case "sctp": 277 return SCTP 278 default: 279 return 0 280 } 281 } 282 283 // GetMacCopy returns a copy of the passed MAC address 284 func GetMacCopy(from net.HardwareAddr) net.HardwareAddr { 285 if from == nil { 286 return nil 287 } 288 to := make(net.HardwareAddr, len(from)) 289 copy(to, from) 290 return to 291 } 292 293 // GetIPCopy returns a copy of the passed IP address 294 func GetIPCopy(from net.IP) net.IP { 295 if from == nil { 296 return nil 297 } 298 to := make(net.IP, len(from)) 299 copy(to, from) 300 return to 301 } 302 303 // GetIPNetCopy returns a copy of the passed IP Network 304 func GetIPNetCopy(from *net.IPNet) *net.IPNet { 305 if from == nil { 306 return nil 307 } 308 bm := make(net.IPMask, len(from.Mask)) 309 copy(bm, from.Mask) 310 return &net.IPNet{IP: GetIPCopy(from.IP), Mask: bm} 311 } 312 313 // GetIPNetCanonical returns the canonical form for the passed network 314 func GetIPNetCanonical(nw *net.IPNet) *net.IPNet { 315 if nw == nil { 316 return nil 317 } 318 c := GetIPNetCopy(nw) 319 c.IP = c.IP.Mask(nw.Mask) 320 return c 321 } 322 323 // CompareIPNet returns equal if the two IP Networks are equal 324 func CompareIPNet(a, b *net.IPNet) bool { 325 if a == b { 326 return true 327 } 328 if a == nil || b == nil { 329 return false 330 } 331 return a.IP.Equal(b.IP) && bytes.Equal(a.Mask, b.Mask) 332 } 333 334 // GetMinimalIP returns the address in its shortest form 335 // If ip contains an IPv4-mapped IPv6 address, the 4-octet form of the IPv4 address will be returned. 336 // Otherwise ip is returned unchanged. 337 func GetMinimalIP(ip net.IP) net.IP { 338 if ip != nil && ip.To4() != nil { 339 return ip.To4() 340 } 341 return ip 342 } 343 344 // GetMinimalIPNet returns a copy of the passed IP Network with congruent ip and mask notation 345 func GetMinimalIPNet(nw *net.IPNet) *net.IPNet { 346 if nw == nil { 347 return nil 348 } 349 if len(nw.IP) == 16 && nw.IP.To4() != nil { 350 m := nw.Mask 351 if len(m) == 16 { 352 m = m[12:16] 353 } 354 return &net.IPNet{IP: nw.IP.To4(), Mask: m} 355 } 356 return nw 357 } 358 359 // IsIPNetValid returns true if the ipnet is a valid network/mask 360 // combination. Otherwise returns false. 361 func IsIPNetValid(nw *net.IPNet) bool { 362 return nw.String() != "0.0.0.0/0" 363 } 364 365 var v4inV6MaskPrefix = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} 366 367 // compareIPMask checks if the passed ip and mask are semantically compatible. 368 // It returns the byte indexes for the address and mask so that caller can 369 // do bitwise operations without modifying address representation. 370 func compareIPMask(ip net.IP, mask net.IPMask) (is int, ms int, err error) { 371 // Find the effective starting of address and mask 372 if len(ip) == net.IPv6len && ip.To4() != nil { 373 is = 12 374 } 375 if len(ip[is:]) == net.IPv4len && len(mask) == net.IPv6len && bytes.Equal(mask[:12], v4inV6MaskPrefix) { 376 ms = 12 377 } 378 // Check if address and mask are semantically compatible 379 if len(ip[is:]) != len(mask[ms:]) { 380 err = fmt.Errorf("ip and mask are not compatible: (%#v, %#v)", ip, mask) 381 } 382 return 383 } 384 385 // GetHostPartIP returns the host portion of the ip address identified by the mask. 386 // IP address representation is not modified. If address and mask are not compatible 387 // an error is returned. 388 func GetHostPartIP(ip net.IP, mask net.IPMask) (net.IP, error) { 389 // Find the effective starting of address and mask 390 is, ms, err := compareIPMask(ip, mask) 391 if err != nil { 392 return nil, fmt.Errorf("cannot compute host portion ip address because %s", err) 393 } 394 395 // Compute host portion 396 out := GetIPCopy(ip) 397 for i := 0; i < len(mask[ms:]); i++ { 398 out[is+i] &= ^mask[ms+i] 399 } 400 401 return out, nil 402 } 403 404 // GetBroadcastIP returns the broadcast ip address for the passed network (ip and mask). 405 // IP address representation is not modified. If address and mask are not compatible 406 // an error is returned. 407 func GetBroadcastIP(ip net.IP, mask net.IPMask) (net.IP, error) { 408 // Find the effective starting of address and mask 409 is, ms, err := compareIPMask(ip, mask) 410 if err != nil { 411 return nil, fmt.Errorf("cannot compute broadcast ip address because %s", err) 412 } 413 414 // Compute broadcast address 415 out := GetIPCopy(ip) 416 for i := 0; i < len(mask[ms:]); i++ { 417 out[is+i] |= ^mask[ms+i] 418 } 419 420 return out, nil 421 } 422 423 // ParseCIDR returns the *net.IPNet represented by the passed CIDR notation 424 func ParseCIDR(cidr string) (n *net.IPNet, e error) { 425 var i net.IP 426 if i, n, e = net.ParseCIDR(cidr); e == nil { 427 n.IP = i 428 } 429 return 430 } 431 432 const ( 433 // NEXTHOP indicates a StaticRoute with an IP next hop. 434 NEXTHOP = iota 435 436 // CONNECTED indicates a StaticRoute with an interface for directly connected peers. 437 CONNECTED 438 ) 439 440 // StaticRoute is a statically-provisioned IP route. 441 type StaticRoute struct { 442 Destination *net.IPNet 443 444 RouteType int // NEXT_HOP or CONNECTED 445 446 // NextHop will be resolved by the kernel (i.e. as a loose hop). 447 NextHop net.IP 448 } 449 450 // GetCopy returns a copy of this StaticRoute structure 451 func (r *StaticRoute) GetCopy() *StaticRoute { 452 d := GetIPNetCopy(r.Destination) 453 nh := GetIPCopy(r.NextHop) 454 return &StaticRoute{Destination: d, 455 RouteType: r.RouteType, 456 NextHop: nh, 457 } 458 } 459 460 // InterfaceStatistics represents the interface's statistics 461 type InterfaceStatistics struct { 462 RxBytes uint64 463 RxPackets uint64 464 RxErrors uint64 465 RxDropped uint64 466 TxBytes uint64 467 TxPackets uint64 468 TxErrors uint64 469 TxDropped uint64 470 } 471 472 func (is *InterfaceStatistics) String() string { 473 return fmt.Sprintf("\nRxBytes: %d, RxPackets: %d, RxErrors: %d, RxDropped: %d, TxBytes: %d, TxPackets: %d, TxErrors: %d, TxDropped: %d", 474 is.RxBytes, is.RxPackets, is.RxErrors, is.RxDropped, is.TxBytes, is.TxPackets, is.TxErrors, is.TxDropped) 475 } 476 477 /****************************** 478 * Well-known Error Interfaces 479 ******************************/ 480 481 // MaskableError is an interface for errors which can be ignored by caller 482 type MaskableError interface { 483 // Maskable makes implementer into MaskableError type 484 Maskable() 485 } 486 487 // RetryError is an interface for errors which might get resolved through retry 488 type RetryError interface { 489 // Retry makes implementer into RetryError type 490 Retry() 491 } 492 493 // BadRequestError is an interface for errors originated by a bad request 494 type BadRequestError interface { 495 // BadRequest makes implementer into BadRequestError type 496 BadRequest() 497 } 498 499 // NotFoundError is an interface for errors raised because a needed resource is not available 500 type NotFoundError interface { 501 // NotFound makes implementer into NotFoundError type 502 NotFound() 503 } 504 505 // ForbiddenError is an interface for errors which denote a valid request that cannot be honored 506 type ForbiddenError interface { 507 // Forbidden makes implementer into ForbiddenError type 508 Forbidden() 509 } 510 511 // NoServiceError is an interface for errors returned when the required service is not available 512 type NoServiceError interface { 513 // NoService makes implementer into NoServiceError type 514 NoService() 515 } 516 517 // TimeoutError is an interface for errors raised because of timeout 518 type TimeoutError interface { 519 // Timeout makes implementer into TimeoutError type 520 Timeout() 521 } 522 523 // NotImplementedError is an interface for errors raised because of requested functionality is not yet implemented 524 type NotImplementedError interface { 525 // NotImplemented makes implementer into NotImplementedError type 526 NotImplemented() 527 } 528 529 // InternalError is an interface for errors raised because of an internal error 530 type InternalError interface { 531 // Internal makes implementer into InternalError type 532 Internal() 533 } 534 535 /****************************** 536 * Well-known Error Formatters 537 ******************************/ 538 539 // BadRequestErrorf creates an instance of BadRequestError 540 func BadRequestErrorf(format string, params ...interface{}) error { 541 return badRequest(fmt.Sprintf(format, params...)) 542 } 543 544 // NotFoundErrorf creates an instance of NotFoundError 545 func NotFoundErrorf(format string, params ...interface{}) error { 546 return notFound(fmt.Sprintf(format, params...)) 547 } 548 549 // ForbiddenErrorf creates an instance of ForbiddenError 550 func ForbiddenErrorf(format string, params ...interface{}) error { 551 return forbidden(fmt.Sprintf(format, params...)) 552 } 553 554 // NoServiceErrorf creates an instance of NoServiceError 555 func NoServiceErrorf(format string, params ...interface{}) error { 556 return noService(fmt.Sprintf(format, params...)) 557 } 558 559 // NotImplementedErrorf creates an instance of NotImplementedError 560 func NotImplementedErrorf(format string, params ...interface{}) error { 561 return notImpl(fmt.Sprintf(format, params...)) 562 } 563 564 // TimeoutErrorf creates an instance of TimeoutError 565 func TimeoutErrorf(format string, params ...interface{}) error { 566 return timeout(fmt.Sprintf(format, params...)) 567 } 568 569 // InternalErrorf creates an instance of InternalError 570 func InternalErrorf(format string, params ...interface{}) error { 571 return internal(fmt.Sprintf(format, params...)) 572 } 573 574 // InternalMaskableErrorf creates an instance of InternalError and MaskableError 575 func InternalMaskableErrorf(format string, params ...interface{}) error { 576 return maskInternal(fmt.Sprintf(format, params...)) 577 } 578 579 // RetryErrorf creates an instance of RetryError 580 func RetryErrorf(format string, params ...interface{}) error { 581 return retry(fmt.Sprintf(format, params...)) 582 } 583 584 /*********************** 585 * Internal Error Types 586 ***********************/ 587 type badRequest string 588 589 func (br badRequest) Error() string { 590 return string(br) 591 } 592 func (br badRequest) BadRequest() {} 593 594 type notFound string 595 596 func (nf notFound) Error() string { 597 return string(nf) 598 } 599 func (nf notFound) NotFound() {} 600 601 type forbidden string 602 603 func (frb forbidden) Error() string { 604 return string(frb) 605 } 606 func (frb forbidden) Forbidden() {} 607 608 type noService string 609 610 func (ns noService) Error() string { 611 return string(ns) 612 } 613 func (ns noService) NoService() {} 614 615 type timeout string 616 617 func (to timeout) Error() string { 618 return string(to) 619 } 620 func (to timeout) Timeout() {} 621 622 type notImpl string 623 624 func (ni notImpl) Error() string { 625 return string(ni) 626 } 627 func (ni notImpl) NotImplemented() {} 628 629 type internal string 630 631 func (nt internal) Error() string { 632 return string(nt) 633 } 634 func (nt internal) Internal() {} 635 636 type maskInternal string 637 638 func (mnt maskInternal) Error() string { 639 return string(mnt) 640 } 641 func (mnt maskInternal) Internal() {} 642 func (mnt maskInternal) Maskable() {} 643 644 type retry string 645 646 func (r retry) Error() string { 647 return string(r) 648 } 649 func (r retry) Retry() {}