github.phpd.cn/hashicorp/packer@v1.3.2/builder/vmware/common/driver_parser.go (about) 1 package common 2 3 import ( 4 "fmt" 5 "io" 6 "log" 7 "math" 8 "net" 9 "os" 10 "reflect" 11 "sort" 12 "strconv" 13 "strings" 14 ) 15 16 type sentinelSignaller chan struct{} 17 18 /** low-level parsing */ 19 // strip the comments and extraneous newlines from a byte channel 20 func uncomment(eof sentinelSignaller, in <-chan byte) (chan byte, sentinelSignaller) { 21 out := make(chan byte) 22 eoc := make(sentinelSignaller) 23 24 go func(in <-chan byte, out chan byte) { 25 var endofline bool 26 for stillReading := true; stillReading; { 27 select { 28 case <-eof: 29 stillReading = false 30 case ch := <-in: 31 switch ch { 32 case '#': 33 endofline = true 34 case '\n': 35 if endofline { 36 endofline = false 37 } 38 } 39 if !endofline { 40 out <- ch 41 } 42 } 43 } 44 close(eoc) 45 }(in, out) 46 return out, eoc 47 } 48 49 // convert a byte channel into a channel of pseudo-tokens 50 func tokenizeDhcpConfig(eof sentinelSignaller, in chan byte) (chan string, sentinelSignaller) { 51 var ch byte 52 var state string 53 var quote bool 54 55 eot := make(sentinelSignaller) 56 57 out := make(chan string) 58 go func(out chan string) { 59 for stillReading := true; stillReading; { 60 select { 61 case <-eof: 62 stillReading = false 63 64 case ch = <-in: 65 if quote { 66 if ch == '"' { 67 out <- state + string(ch) 68 state, quote = "", false 69 continue 70 } 71 state += string(ch) 72 continue 73 } 74 75 switch ch { 76 case '"': 77 quote = true 78 state += string(ch) 79 continue 80 81 case '\r': 82 fallthrough 83 case '\n': 84 fallthrough 85 case '\t': 86 fallthrough 87 case ' ': 88 if len(state) == 0 { 89 continue 90 } 91 out <- state 92 state = "" 93 94 case '{': 95 fallthrough 96 case '}': 97 fallthrough 98 case ';': 99 if len(state) > 0 { 100 out <- state 101 } 102 out <- string(ch) 103 state = "" 104 105 default: 106 state += string(ch) 107 } 108 } 109 } 110 if len(state) > 0 { 111 out <- state 112 } 113 close(eot) 114 }(out) 115 return out, eot 116 } 117 118 /** mid-level parsing */ 119 type tkParameter struct { 120 name string 121 operand []string 122 } 123 124 func (e *tkParameter) String() string { 125 var values []string 126 for _, val := range e.operand { 127 values = append(values, val) 128 } 129 return fmt.Sprintf("%s [%s]", e.name, strings.Join(values, ",")) 130 } 131 132 type tkGroup struct { 133 parent *tkGroup 134 id tkParameter 135 136 groups []*tkGroup 137 params []tkParameter 138 } 139 140 func (e *tkGroup) String() string { 141 var id []string 142 143 id = append(id, e.id.name) 144 for _, val := range e.id.operand { 145 id = append(id, val) 146 } 147 148 var config []string 149 for _, val := range e.params { 150 config = append(config, val.String()) 151 } 152 return fmt.Sprintf("%s {\n%s\n}", strings.Join(id, " "), strings.Join(config, "\n")) 153 } 154 155 // convert a channel of pseudo-tokens into an tkParameter struct 156 func parseTokenParameter(in chan string) tkParameter { 157 var result tkParameter 158 for { 159 token := <-in 160 if result.name == "" { 161 result.name = token 162 continue 163 } 164 switch token { 165 case "{": 166 fallthrough 167 case "}": 168 fallthrough 169 case ";": 170 goto leave 171 default: 172 result.operand = append(result.operand, token) 173 } 174 } 175 leave: 176 return result 177 } 178 179 // convert a channel of pseudo-tokens into an tkGroup tree */ 180 func parseDhcpConfig(eof sentinelSignaller, in chan string) (tkGroup, error) { 181 var tokens []string 182 var result tkGroup 183 184 toParameter := func(tokens []string) tkParameter { 185 out := make(chan string) 186 go func(out chan string) { 187 for _, v := range tokens { 188 out <- v 189 } 190 out <- ";" 191 }(out) 192 return parseTokenParameter(out) 193 } 194 195 for stillReading, currentgroup := true, &result; stillReading; { 196 select { 197 case <-eof: 198 stillReading = false 199 200 case tk := <-in: 201 switch tk { 202 case "{": 203 grp := &tkGroup{parent: currentgroup} 204 grp.id = toParameter(tokens) 205 currentgroup.groups = append(currentgroup.groups, grp) 206 currentgroup = grp 207 case "}": 208 if currentgroup.parent == nil { 209 return tkGroup{}, fmt.Errorf("Unable to close the global declaration") 210 } 211 if len(tokens) > 0 { 212 return tkGroup{}, fmt.Errorf("List of tokens was left unterminated : %v", tokens) 213 } 214 currentgroup = currentgroup.parent 215 case ";": 216 arg := toParameter(tokens) 217 currentgroup.params = append(currentgroup.params, arg) 218 default: 219 tokens = append(tokens, tk) 220 continue 221 } 222 tokens = []string{} 223 } 224 } 225 return result, nil 226 } 227 228 func tokenizeNetworkMapConfig(eof sentinelSignaller, in chan byte) (chan string, sentinelSignaller) { 229 var ch byte 230 var state string 231 var quote bool 232 var lastnewline bool 233 234 eot := make(sentinelSignaller) 235 236 out := make(chan string) 237 go func(out chan string) { 238 for stillReading := true; stillReading; { 239 select { 240 case <-eof: 241 stillReading = false 242 243 case ch = <-in: 244 if quote { 245 if ch == '"' { 246 out <- state + string(ch) 247 state, quote = "", false 248 continue 249 } 250 state += string(ch) 251 continue 252 } 253 254 switch ch { 255 case '"': 256 quote = true 257 state += string(ch) 258 continue 259 260 case '\r': 261 fallthrough 262 case '\t': 263 fallthrough 264 case ' ': 265 if len(state) == 0 { 266 continue 267 } 268 out <- state 269 state = "" 270 271 case '\n': 272 if lastnewline { 273 continue 274 } 275 if len(state) > 0 { 276 out <- state 277 } 278 out <- string(ch) 279 state = "" 280 lastnewline = true 281 continue 282 283 case '.': 284 fallthrough 285 case '=': 286 if len(state) > 0 { 287 out <- state 288 } 289 out <- string(ch) 290 state = "" 291 292 default: 293 state += string(ch) 294 } 295 lastnewline = false 296 } 297 } 298 if len(state) > 0 { 299 out <- state 300 } 301 close(eot) 302 }(out) 303 return out, eot 304 } 305 306 func parseNetworkMapConfig(eof sentinelSignaller, in chan string) (NetworkMap, error) { 307 var unsorted map[string]map[string]string 308 var state []string 309 310 addResult := func(network string, attribute string, value string) error { 311 _, ok := unsorted[network] 312 if !ok { 313 unsorted[network] = make(map[string]string) 314 } 315 316 val, err := strconv.Unquote(value) 317 if err != nil { 318 return err 319 } 320 321 current := unsorted[network] 322 current[attribute] = val 323 return nil 324 } 325 326 stillReading := true 327 for unsorted = make(map[string]map[string]string); stillReading; { 328 select { 329 case <-eof: 330 if len(state) == 3 { 331 err := addResult(state[0], state[1], state[2]) 332 if err != nil { 333 return nil, err 334 } 335 } 336 stillReading = false 337 case tk := <-in: 338 switch tk { 339 case ".": 340 if len(state) != 1 { 341 return nil, fmt.Errorf("Missing network index") 342 } 343 case "=": 344 if len(state) != 2 { 345 return nil, fmt.Errorf("Assignment to empty attribute") 346 } 347 case "\n": 348 if len(state) == 0 { 349 continue 350 } 351 if len(state) != 3 { 352 return nil, fmt.Errorf("Invalid attribute assignment : %v", state) 353 } 354 err := addResult(state[0], state[1], state[2]) 355 if err != nil { 356 return nil, err 357 } 358 state = make([]string, 0) 359 default: 360 state = append(state, tk) 361 } 362 } 363 } 364 result := make([]map[string]string, 0) 365 var keys []string 366 for k := range unsorted { 367 keys = append(keys, k) 368 } 369 sort.Strings(keys) 370 for _, k := range keys { 371 result = append(result, unsorted[k]) 372 } 373 return result, nil 374 } 375 376 /** higher-level parsing */ 377 /// parameters 378 type pParameter interface { 379 repr() string 380 } 381 382 type pParameterInclude struct { 383 filename string 384 } 385 386 func (e pParameterInclude) repr() string { return fmt.Sprintf("include-file:filename=%s", e.filename) } 387 388 type pParameterOption struct { 389 name string 390 value string 391 } 392 393 func (e pParameterOption) repr() string { return fmt.Sprintf("option:%s=%s", e.name, e.value) } 394 395 // allow some-kind-of-something 396 type pParameterGrant struct { 397 verb string // allow,deny,ignore 398 attribute string 399 } 400 401 func (e pParameterGrant) repr() string { return fmt.Sprintf("grant:%s,%s", e.verb, e.attribute) } 402 403 type pParameterAddress4 []string 404 405 func (e pParameterAddress4) repr() string { 406 return fmt.Sprintf("fixed-address4:%s", strings.Join(e, ",")) 407 } 408 409 type pParameterAddress6 []string 410 411 func (e pParameterAddress6) repr() string { 412 return fmt.Sprintf("fixed-address6:%s", strings.Join(e, ",")) 413 } 414 415 // hardware address 00:00:00:00:00:00 416 type pParameterHardware struct { 417 class string 418 address []byte 419 } 420 421 func (e pParameterHardware) repr() string { 422 res := make([]string, 0) 423 for _, v := range e.address { 424 res = append(res, fmt.Sprintf("%02x", v)) 425 } 426 return fmt.Sprintf("hardware-address:%s[%s]", e.class, strings.Join(res, ":")) 427 } 428 429 type pParameterBoolean struct { 430 parameter string 431 truancy bool 432 } 433 434 func (e pParameterBoolean) repr() string { return fmt.Sprintf("boolean:%s=%v", e.parameter, e.truancy) } 435 436 type pParameterClientMatch struct { 437 name string 438 data string 439 } 440 441 func (e pParameterClientMatch) repr() string { return fmt.Sprintf("match-client:%s=%s", e.name, e.data) } 442 443 // range 127.0.0.1 127.0.0.255 444 type pParameterRange4 struct { 445 min net.IP 446 max net.IP 447 } 448 449 func (e pParameterRange4) repr() string { 450 return fmt.Sprintf("range4:%s-%s", e.min.String(), e.max.String()) 451 } 452 453 type pParameterRange6 struct { 454 min net.IP 455 max net.IP 456 } 457 458 func (e pParameterRange6) repr() string { 459 return fmt.Sprintf("range6:%s-%s", e.min.String(), e.max.String()) 460 } 461 462 type pParameterPrefix6 struct { 463 min net.IP 464 max net.IP 465 bits int 466 } 467 468 func (e pParameterPrefix6) repr() string { 469 return fmt.Sprintf("prefix6:/%d:%s-%s", e.bits, e.min.String(), e.max.String()) 470 } 471 472 // some-kind-of-parameter 1024 473 type pParameterOther struct { 474 parameter string 475 value string 476 } 477 478 func (e pParameterOther) repr() string { return fmt.Sprintf("parameter:%s=%s", e.parameter, e.value) } 479 480 type pParameterExpression struct { 481 parameter string 482 expression string 483 } 484 485 func (e pParameterExpression) repr() string { 486 return fmt.Sprintf("parameter-expression:%s=\"%s\"", e.parameter, e.expression) 487 } 488 489 type pDeclarationIdentifier interface { 490 repr() string 491 } 492 493 type pDeclaration struct { 494 id pDeclarationIdentifier 495 parent *pDeclaration 496 parameters []pParameter 497 declarations []pDeclaration 498 } 499 500 func (e *pDeclaration) short() string { 501 return e.id.repr() 502 } 503 504 func (e *pDeclaration) repr() string { 505 res := e.short() 506 507 var parameters []string 508 for _, v := range e.parameters { 509 parameters = append(parameters, v.repr()) 510 } 511 512 var groups []string 513 for _, v := range e.declarations { 514 groups = append(groups, fmt.Sprintf("-> %s", v.short())) 515 } 516 517 if e.parent != nil { 518 res = fmt.Sprintf("%s parent:%s", res, e.parent.short()) 519 } 520 return fmt.Sprintf("%s\n%s\n%s\n", res, strings.Join(parameters, "\n"), strings.Join(groups, "\n")) 521 } 522 523 type pDeclarationGlobal struct{} 524 525 func (e pDeclarationGlobal) repr() string { return fmt.Sprintf("{global}") } 526 527 type pDeclarationShared struct{ name string } 528 529 func (e pDeclarationShared) repr() string { return fmt.Sprintf("{shared-network %s}", e.name) } 530 531 type pDeclarationSubnet4 struct{ net.IPNet } 532 533 func (e pDeclarationSubnet4) repr() string { return fmt.Sprintf("{subnet4 %s}", e.String()) } 534 535 type pDeclarationSubnet6 struct{ net.IPNet } 536 537 func (e pDeclarationSubnet6) repr() string { return fmt.Sprintf("{subnet6 %s}", e.String()) } 538 539 type pDeclarationHost struct{ name string } 540 541 func (e pDeclarationHost) repr() string { return fmt.Sprintf("{host name:%s}", e.name) } 542 543 type pDeclarationPool struct{} 544 545 func (e pDeclarationPool) repr() string { return fmt.Sprintf("{pool}") } 546 547 type pDeclarationGroup struct{} 548 549 func (e pDeclarationGroup) repr() string { return fmt.Sprintf("{group}") } 550 551 type pDeclarationClass struct{ name string } 552 553 func (e pDeclarationClass) repr() string { return fmt.Sprintf("{class}") } 554 555 /** parsers */ 556 func parseParameter(val tkParameter) (pParameter, error) { 557 switch val.name { 558 case "include": 559 if len(val.operand) != 2 { 560 return nil, fmt.Errorf("Invalid number of parameters for pParameterInclude : %v", val.operand) 561 } 562 name := val.operand[0] 563 return pParameterInclude{filename: name}, nil 564 565 case "option": 566 if len(val.operand) != 2 { 567 return nil, fmt.Errorf("Invalid number of parameters for pParameterOption : %v", val.operand) 568 } 569 name, value := val.operand[0], val.operand[1] 570 return pParameterOption{name: name, value: value}, nil 571 572 case "allow": 573 fallthrough 574 case "deny": 575 fallthrough 576 case "ignore": 577 if len(val.operand) < 1 { 578 return nil, fmt.Errorf("Invalid number of parameters for pParameterGrant : %v", val.operand) 579 } 580 attribute := strings.Join(val.operand, " ") 581 return pParameterGrant{verb: strings.ToLower(val.name), attribute: attribute}, nil 582 583 case "range": 584 if len(val.operand) < 1 { 585 return nil, fmt.Errorf("Invalid number of parameters for pParameterRange4 : %v", val.operand) 586 } 587 idxAddress := map[bool]int{true: 1, false: 0}[strings.ToLower(val.operand[0]) == "bootp"] 588 if len(val.operand) > 2+idxAddress { 589 return nil, fmt.Errorf("Invalid number of parameters for pParameterRange : %v", val.operand) 590 } 591 if idxAddress+1 > len(val.operand) { 592 res := net.ParseIP(val.operand[idxAddress]) 593 return pParameterRange4{min: res, max: res}, nil 594 } 595 addr1 := net.ParseIP(val.operand[idxAddress]) 596 addr2 := net.ParseIP(val.operand[idxAddress+1]) 597 return pParameterRange4{min: addr1, max: addr2}, nil 598 599 case "range6": 600 if len(val.operand) == 1 { 601 address := val.operand[0] 602 if strings.Contains(address, "/") { 603 cidr := strings.SplitN(address, "/", 2) 604 if len(cidr) != 2 { 605 return nil, fmt.Errorf("Unknown ipv6 format : %v", address) 606 } 607 address := net.ParseIP(cidr[0]) 608 bits, err := strconv.Atoi(cidr[1]) 609 if err != nil { 610 return nil, err 611 } 612 mask := net.CIDRMask(bits, net.IPv6len*8) 613 614 // figure out the network address 615 network := address.Mask(mask) 616 617 // make a broadcast address 618 broadcast := network 619 networkSize, totalSize := mask.Size() 620 hostSize := totalSize - networkSize 621 for i := networkSize / 8; i < totalSize/8; i++ { 622 broadcast[i] = byte(0xff) 623 } 624 octetIndex := network[networkSize/8] 625 bitsLeft := (uint32)(hostSize % 8) 626 broadcast[octetIndex] = network[octetIndex] | ((1 << bitsLeft) - 1) 627 628 // FIXME: check that the broadcast address was made correctly 629 return pParameterRange6{min: network, max: broadcast}, nil 630 } 631 res := net.ParseIP(address) 632 return pParameterRange6{min: res, max: res}, nil 633 } 634 if len(val.operand) == 2 { 635 addr := net.ParseIP(val.operand[0]) 636 if strings.ToLower(val.operand[1]) == "temporary" { 637 return pParameterRange6{min: addr, max: addr}, nil 638 } 639 other := net.ParseIP(val.operand[1]) 640 return pParameterRange6{min: addr, max: other}, nil 641 } 642 return nil, fmt.Errorf("Invalid number of parameters for pParameterRange6 : %v", val.operand) 643 644 case "prefix6": 645 if len(val.operand) != 3 { 646 return nil, fmt.Errorf("Invalid number of parameters for pParameterRange6 : %v", val.operand) 647 } 648 bits, err := strconv.Atoi(val.operand[2]) 649 if err != nil { 650 return nil, fmt.Errorf("Invalid bits for pParameterPrefix6 : %v", val.operand[2]) 651 } 652 minaddr := net.ParseIP(val.operand[0]) 653 maxaddr := net.ParseIP(val.operand[1]) 654 return pParameterPrefix6{min: minaddr, max: maxaddr, bits: bits}, nil 655 656 case "hardware": 657 if len(val.operand) != 2 { 658 return nil, fmt.Errorf("Invalid number of parameters for pParameterHardware : %v", val.operand) 659 } 660 class := val.operand[0] 661 octets := strings.Split(val.operand[1], ":") 662 address := make([]byte, 0) 663 for _, v := range octets { 664 b, err := strconv.ParseInt(v, 16, 0) 665 if err != nil { 666 return nil, err 667 } 668 address = append(address, byte(b)) 669 } 670 return pParameterHardware{class: class, address: address}, nil 671 672 case "fixed-address": 673 ip4addrs := make(pParameterAddress4, len(val.operand)) 674 copy(ip4addrs, val.operand) 675 return ip4addrs, nil 676 677 case "fixed-address6": 678 ip6addrs := make(pParameterAddress6, len(val.operand)) 679 copy(ip6addrs, val.operand) 680 return ip6addrs, nil 681 682 case "host-identifier": 683 if len(val.operand) != 3 { 684 return nil, fmt.Errorf("Invalid number of parameters for pParameterClientMatch : %v", val.operand) 685 } 686 if val.operand[0] != "option" { 687 return nil, fmt.Errorf("Invalid match parameter : %v", val.operand[0]) 688 } 689 optionName := val.operand[1] 690 optionData := val.operand[2] 691 return pParameterClientMatch{name: optionName, data: optionData}, nil 692 693 default: 694 length := len(val.operand) 695 if length < 1 { 696 return pParameterBoolean{parameter: val.name, truancy: true}, nil 697 } else if length > 1 { 698 if val.operand[0] == "=" { 699 return pParameterExpression{parameter: val.name, expression: strings.Join(val.operand[1:], "")}, nil 700 } 701 } 702 if length != 1 { 703 return nil, fmt.Errorf("Invalid number of parameters for pParameterOther : %v", val.operand) 704 } 705 if strings.ToLower(val.name) == "not" { 706 return pParameterBoolean{parameter: val.operand[0], truancy: false}, nil 707 } 708 return pParameterOther{parameter: val.name, value: val.operand[0]}, nil 709 } 710 } 711 712 func parseTokenGroup(val tkGroup) (*pDeclaration, error) { 713 params := val.id.operand 714 switch val.id.name { 715 case "group": 716 return &pDeclaration{id: pDeclarationGroup{}}, nil 717 718 case "pool": 719 return &pDeclaration{id: pDeclarationPool{}}, nil 720 721 case "host": 722 if len(params) == 1 { 723 return &pDeclaration{id: pDeclarationHost{name: params[0]}}, nil 724 } 725 726 case "subnet": 727 if len(params) == 3 && strings.ToLower(params[1]) == "netmask" { 728 addr := make([]byte, 4) 729 for i, v := range strings.SplitN(params[2], ".", 4) { 730 res, err := strconv.ParseInt(v, 10, 0) 731 if err != nil { 732 return nil, err 733 } 734 addr[i] = byte(res) 735 } 736 oc1, oc2, oc3, oc4 := addr[0], addr[1], addr[2], addr[3] 737 if subnet, mask := net.ParseIP(params[0]), net.IPv4Mask(oc1, oc2, oc3, oc4); subnet != nil && mask != nil { 738 return &pDeclaration{id: pDeclarationSubnet4{net.IPNet{IP: subnet, Mask: mask}}}, nil 739 } 740 } 741 case "subnet6": 742 if len(params) == 1 { 743 ip6 := strings.SplitN(params[0], "/", 2) 744 if len(ip6) == 2 && strings.Contains(ip6[0], ":") { 745 address := net.ParseIP(ip6[0]) 746 prefix, err := strconv.Atoi(ip6[1]) 747 if err != nil { 748 return nil, err 749 } 750 return &pDeclaration{id: pDeclarationSubnet6{net.IPNet{IP: address, Mask: net.CIDRMask(prefix, net.IPv6len*8)}}}, nil 751 } 752 } 753 case "shared-network": 754 if len(params) == 1 { 755 return &pDeclaration{id: pDeclarationShared{name: params[0]}}, nil 756 } 757 case "": 758 return &pDeclaration{id: pDeclarationGlobal{}}, nil 759 } 760 return nil, fmt.Errorf("Invalid pDeclaration : %v : %v", val.id.name, params) 761 } 762 763 func flattenDhcpConfig(root tkGroup) (*pDeclaration, error) { 764 var result *pDeclaration 765 result, err := parseTokenGroup(root) 766 if err != nil { 767 return nil, err 768 } 769 770 for _, p := range root.params { 771 param, err := parseParameter(p) 772 if err != nil { 773 return nil, err 774 } 775 result.parameters = append(result.parameters, param) 776 } 777 for _, p := range root.groups { 778 group, err := flattenDhcpConfig(*p) 779 if err != nil { 780 return nil, err 781 } 782 group.parent = result 783 result.declarations = append(result.declarations, *group) 784 } 785 return result, nil 786 } 787 788 /** reduce the tree into the things that we care about */ 789 type grant uint 790 791 const ( 792 ALLOW grant = iota 793 IGNORE grant = iota 794 DENY grant = iota 795 ) 796 797 type configDeclaration struct { 798 id []pDeclarationIdentifier 799 composites []pDeclaration 800 801 address []pParameter 802 803 options map[string]string 804 grants map[string]grant 805 attributes map[string]bool 806 parameters map[string]string 807 expressions map[string]string 808 809 hostid []pParameterClientMatch 810 } 811 812 func createDeclaration(node pDeclaration) configDeclaration { 813 var hierarchy []pDeclaration 814 815 for n := &node; n != nil; n = n.parent { 816 hierarchy = append(hierarchy, *n) 817 } 818 819 var result configDeclaration 820 result.address = make([]pParameter, 0) 821 822 result.options = make(map[string]string) 823 result.grants = make(map[string]grant) 824 result.attributes = make(map[string]bool) 825 result.parameters = make(map[string]string) 826 result.expressions = make(map[string]string) 827 828 result.hostid = make([]pParameterClientMatch, 0) 829 830 // walk from globals to pDeclaration collecting all parameters 831 for i := len(hierarchy) - 1; i >= 0; i-- { 832 result.composites = append(result.composites, hierarchy[(len(hierarchy)-1)-i]) 833 result.id = append(result.id, hierarchy[(len(hierarchy)-1)-i].id) 834 835 // update configDeclaration parameters 836 for _, p := range hierarchy[i].parameters { 837 switch p.(type) { 838 case pParameterOption: 839 result.options[p.(pParameterOption).name] = p.(pParameterOption).value 840 case pParameterGrant: 841 Grant := map[string]grant{"ignore": IGNORE, "allow": ALLOW, "deny": DENY} 842 result.grants[p.(pParameterGrant).attribute] = Grant[p.(pParameterGrant).verb] 843 case pParameterBoolean: 844 result.attributes[p.(pParameterBoolean).parameter] = p.(pParameterBoolean).truancy 845 case pParameterClientMatch: 846 result.hostid = append(result.hostid, p.(pParameterClientMatch)) 847 case pParameterExpression: 848 result.expressions[p.(pParameterExpression).parameter] = p.(pParameterExpression).expression 849 case pParameterOther: 850 result.parameters[p.(pParameterOther).parameter] = p.(pParameterOther).value 851 default: 852 result.address = append(result.address, p) 853 } 854 } 855 } 856 return result 857 } 858 859 func (e *configDeclaration) repr() string { 860 var result []string 861 862 var res []string 863 864 res = make([]string, 0) 865 for _, v := range e.id { 866 res = append(res, v.repr()) 867 } 868 result = append(result, strings.Join(res, ",")) 869 870 if len(e.address) > 0 { 871 res = make([]string, 0) 872 for _, v := range e.address { 873 res = append(res, v.repr()) 874 } 875 result = append(result, fmt.Sprintf("address : %v", strings.Join(res, ","))) 876 } 877 878 if len(e.options) > 0 { 879 result = append(result, fmt.Sprintf("options : %v", e.options)) 880 } 881 if len(e.grants) > 0 { 882 result = append(result, fmt.Sprintf("grants : %v", e.grants)) 883 } 884 if len(e.attributes) > 0 { 885 result = append(result, fmt.Sprintf("attributes : %v", e.attributes)) 886 } 887 if len(e.parameters) > 0 { 888 result = append(result, fmt.Sprintf("parameters : %v", e.parameters)) 889 } 890 if len(e.expressions) > 0 { 891 result = append(result, fmt.Sprintf("parameter-expressions : %v", e.expressions)) 892 } 893 894 if len(e.hostid) > 0 { 895 res = make([]string, 0) 896 for _, v := range e.hostid { 897 res = append(res, v.repr()) 898 } 899 result = append(result, fmt.Sprintf("hostid : %v", strings.Join(res, " "))) 900 } 901 return strings.Join(result, "\n") + "\n" 902 } 903 904 func (e *configDeclaration) IP4() (net.IP, error) { 905 var result []string 906 for _, entry := range e.address { 907 switch entry.(type) { 908 case pParameterAddress4: 909 for _, s := range entry.(pParameterAddress4) { 910 result = append(result, s) 911 } 912 } 913 } 914 if len(result) > 1 { 915 return nil, fmt.Errorf("More than one address4 returned : %v", result) 916 } else if len(result) == 0 { 917 return nil, fmt.Errorf("No IP4 addresses found") 918 } 919 920 if res := net.ParseIP(result[0]); res != nil { 921 return res, nil 922 } 923 res, err := net.ResolveIPAddr("ip4", result[0]) 924 if err != nil { 925 return nil, err 926 } 927 return res.IP, nil 928 } 929 func (e *configDeclaration) IP6() (net.IP, error) { 930 var result []string 931 for _, entry := range e.address { 932 switch entry.(type) { 933 case pParameterAddress6: 934 for _, s := range entry.(pParameterAddress6) { 935 result = append(result, s) 936 } 937 } 938 } 939 if len(result) > 1 { 940 return nil, fmt.Errorf("More than one address6 returned : %v", result) 941 } else if len(result) == 0 { 942 return nil, fmt.Errorf("No IP6 addresses found") 943 } 944 945 if res := net.ParseIP(result[0]); res != nil { 946 return res, nil 947 } 948 res, err := net.ResolveIPAddr("ip6", result[0]) 949 if err != nil { 950 return nil, err 951 } 952 return res.IP, nil 953 } 954 func (e *configDeclaration) Hardware() (net.HardwareAddr, error) { 955 var result []pParameterHardware 956 for _, addr := range e.address { 957 switch addr.(type) { 958 case pParameterHardware: 959 result = append(result, addr.(pParameterHardware)) 960 } 961 } 962 if len(result) > 0 { 963 return nil, fmt.Errorf("More than one hardware address returned : %v", result) 964 } 965 res := make(net.HardwareAddr, 0) 966 for _, by := range result[0].address { 967 res = append(res, by) 968 } 969 return res, nil 970 } 971 972 /*** Dhcp Configuration */ 973 type DhcpConfiguration []configDeclaration 974 975 func ReadDhcpConfiguration(fd *os.File) (DhcpConfiguration, error) { 976 fromfile, eof := consumeFile(fd) 977 uncommented, eoc := uncomment(eof, fromfile) 978 tokenized, eot := tokenizeDhcpConfig(eoc, uncommented) 979 parsetree, err := parseDhcpConfig(eot, tokenized) 980 if err != nil { 981 return nil, err 982 } 983 984 global, err := flattenDhcpConfig(parsetree) 985 if err != nil { 986 return nil, err 987 } 988 989 var walkDeclarations func(root pDeclaration, out chan *configDeclaration) 990 walkDeclarations = func(root pDeclaration, out chan *configDeclaration) { 991 res := createDeclaration(root) 992 out <- &res 993 for _, p := range root.declarations { 994 walkDeclarations(p, out) 995 } 996 } 997 998 each := make(chan *configDeclaration) 999 go func(out chan *configDeclaration) { 1000 walkDeclarations(*global, out) 1001 out <- nil 1002 }(each) 1003 1004 var result DhcpConfiguration 1005 for decl := <-each; decl != nil; decl = <-each { 1006 result = append(result, *decl) 1007 } 1008 return result, nil 1009 } 1010 1011 func (e *DhcpConfiguration) Global() configDeclaration { 1012 result := (*e)[0] 1013 if len(result.id) != 1 { 1014 panic(fmt.Errorf("Something that can't happen happened")) 1015 } 1016 return result 1017 } 1018 1019 func (e *DhcpConfiguration) SubnetByAddress(address net.IP) (configDeclaration, error) { 1020 var result []configDeclaration 1021 for _, entry := range *e { 1022 switch entry.id[0].(type) { 1023 case pDeclarationSubnet4: 1024 id := entry.id[0].(pDeclarationSubnet4) 1025 if id.Contains(address) { 1026 result = append(result, entry) 1027 } 1028 case pDeclarationSubnet6: 1029 id := entry.id[0].(pDeclarationSubnet6) 1030 if id.Contains(address) { 1031 result = append(result, entry) 1032 } 1033 } 1034 } 1035 if len(result) == 0 { 1036 return configDeclaration{}, fmt.Errorf("No network declarations containing %s found", address.String()) 1037 } 1038 if len(result) > 1 { 1039 return configDeclaration{}, fmt.Errorf("More than 1 network declaration found : %v", result) 1040 } 1041 return result[0], nil 1042 } 1043 1044 func (e *DhcpConfiguration) HostByName(host string) (configDeclaration, error) { 1045 var result []configDeclaration 1046 for _, entry := range *e { 1047 switch entry.id[0].(type) { 1048 case pDeclarationHost: 1049 id := entry.id[0].(pDeclarationHost) 1050 if strings.ToLower(id.name) == strings.ToLower(host) { 1051 result = append(result, entry) 1052 } 1053 } 1054 } 1055 if len(result) == 0 { 1056 return configDeclaration{}, fmt.Errorf("No host declarations containing %s found", host) 1057 } 1058 if len(result) > 1 { 1059 return configDeclaration{}, fmt.Errorf("More than 1 host declaration found : %v", result) 1060 } 1061 return result[0], nil 1062 } 1063 1064 /*** Network Map */ 1065 type NetworkMap []map[string]string 1066 1067 type NetworkNameMapper interface { 1068 NameIntoDevices(string) ([]string, error) 1069 DeviceIntoName(string) (string, error) 1070 } 1071 1072 func ReadNetworkMap(fd *os.File) (NetworkMap, error) { 1073 1074 fromfile, eof := consumeFile(fd) 1075 uncommented, eoc := uncomment(eof, fromfile) 1076 tokenized, eot := tokenizeNetworkMapConfig(eoc, uncommented) 1077 1078 result, err := parseNetworkMapConfig(eot, tokenized) 1079 if err != nil { 1080 return nil, err 1081 } 1082 return result, nil 1083 } 1084 1085 func (e NetworkMap) NameIntoDevices(name string) ([]string, error) { 1086 var devices []string 1087 for _, val := range e { 1088 if strings.ToLower(val["name"]) == strings.ToLower(name) { 1089 devices = append(devices, val["device"]) 1090 } 1091 } 1092 if len(devices) > 0 { 1093 return devices, nil 1094 } 1095 return make([]string, 0), fmt.Errorf("Network name not found : %v", name) 1096 } 1097 func (e NetworkMap) DeviceIntoName(device string) (string, error) { 1098 for _, val := range e { 1099 if strings.ToLower(val["device"]) == strings.ToLower(device) { 1100 return val["name"], nil 1101 } 1102 } 1103 return "", fmt.Errorf("Device name not found : %v", device) 1104 } 1105 func (e *NetworkMap) repr() string { 1106 var result []string 1107 for idx, val := range *e { 1108 result = append(result, fmt.Sprintf("network%d.name = \"%s\"", idx, val["name"])) 1109 result = append(result, fmt.Sprintf("network%d.device = \"%s\"", idx, val["device"])) 1110 } 1111 return strings.Join(result, "\n") 1112 } 1113 1114 /*** parser for VMware Fusion's networking file */ 1115 func tokenizeNetworkingConfig(eof sentinelSignaller, in chan byte) (chan string, sentinelSignaller) { 1116 var ch byte 1117 var state string 1118 var repeat_newline bool 1119 1120 eot := make(sentinelSignaller) 1121 1122 out := make(chan string) 1123 go func(out chan string) { 1124 for reading := true; reading; { 1125 select { 1126 case <-eof: 1127 reading = false 1128 1129 case ch = <-in: 1130 switch ch { 1131 case '\r': 1132 fallthrough 1133 case '\t': 1134 fallthrough 1135 case ' ': 1136 if len(state) == 0 { 1137 continue 1138 } 1139 out <- state 1140 state = "" 1141 case '\n': 1142 if repeat_newline { 1143 continue 1144 } 1145 if len(state) > 0 { 1146 out <- state 1147 } 1148 out <- string(ch) 1149 state = "" 1150 repeat_newline = true 1151 continue 1152 default: 1153 state += string(ch) 1154 } 1155 repeat_newline = false 1156 } 1157 } 1158 if len(state) > 0 { 1159 out <- state 1160 } 1161 close(eot) 1162 }(out) 1163 return out, eot 1164 } 1165 1166 func splitNetworkingConfig(eof sentinelSignaller, in chan string) (chan []string, sentinelSignaller) { 1167 var out chan []string 1168 1169 eos := make(sentinelSignaller) 1170 1171 out = make(chan []string) 1172 go func(out chan []string) { 1173 row := make([]string, 0) 1174 for reading := true; reading; { 1175 select { 1176 case <-eof: 1177 reading = false 1178 1179 case tk := <-in: 1180 switch tk { 1181 case "\n": 1182 if len(row) > 0 { 1183 out <- row 1184 } 1185 row = make([]string, 0) 1186 default: 1187 row = append(row, tk) 1188 } 1189 } 1190 } 1191 if len(row) > 0 { 1192 out <- row 1193 } 1194 close(eos) 1195 }(out) 1196 return out, eos 1197 } 1198 1199 /// All token types in networking file. 1200 // VERSION token 1201 type networkingVERSION struct { 1202 value string 1203 } 1204 1205 func networkingReadVersion(row []string) (*networkingVERSION, error) { 1206 if len(row) != 1 { 1207 return nil, fmt.Errorf("Unexpected format for VERSION entry : %v", row) 1208 } 1209 res := &networkingVERSION{value: row[0]} 1210 if !res.Valid() { 1211 return nil, fmt.Errorf("Unexpected format for VERSION entry : %v", row) 1212 } 1213 return res, nil 1214 } 1215 1216 func (s networkingVERSION) Repr() string { 1217 if !s.Valid() { 1218 return fmt.Sprintf("VERSION{INVALID=\"%v\"}", s.value) 1219 } 1220 return fmt.Sprintf("VERSION{%f}", s.Number()) 1221 } 1222 1223 func (s networkingVERSION) Valid() bool { 1224 tokens := strings.SplitN(s.value, "=", 2) 1225 if len(tokens) != 2 || tokens[0] != "VERSION" { 1226 return false 1227 } 1228 1229 tokens = strings.Split(tokens[1], ",") 1230 if len(tokens) != 2 { 1231 return false 1232 } 1233 1234 for _, t := range tokens { 1235 _, err := strconv.ParseUint(t, 10, 64) 1236 if err != nil { 1237 return false 1238 } 1239 } 1240 return true 1241 } 1242 1243 func (s networkingVERSION) Number() float64 { 1244 var result float64 1245 tokens := strings.SplitN(s.value, "=", 2) 1246 tokens = strings.Split(tokens[1], ",") 1247 1248 integer, err := strconv.ParseUint(tokens[0], 10, 64) 1249 if err != nil { 1250 integer = 0 1251 } 1252 result = float64(integer) 1253 1254 mantissa, err := strconv.ParseUint(tokens[1], 10, 64) 1255 if err != nil { 1256 return result 1257 } 1258 denomination := math.Pow(10.0, float64(len(tokens[1]))) 1259 return result + (float64(mantissa) / denomination) 1260 } 1261 1262 // VNET_X token 1263 type networkingVNET struct { 1264 value string 1265 } 1266 1267 func (s networkingVNET) Valid() bool { 1268 if strings.ToUpper(s.value) != s.value { 1269 return false 1270 } 1271 tokens := strings.SplitN(s.value, "_", 3) 1272 if len(tokens) != 3 || tokens[0] != "VNET" { 1273 return false 1274 } 1275 _, err := strconv.ParseUint(tokens[1], 10, 64) 1276 if err != nil { 1277 return false 1278 } 1279 return true 1280 } 1281 1282 func (s networkingVNET) Number() int { 1283 tokens := strings.SplitN(s.value, "_", 3) 1284 res, err := strconv.Atoi(tokens[1]) 1285 if err != nil { 1286 return ^int(0) 1287 } 1288 return res 1289 } 1290 1291 func (s networkingVNET) Option() string { 1292 tokens := strings.SplitN(s.value, "_", 3) 1293 if len(tokens) == 3 { 1294 return tokens[2] 1295 } 1296 return "" 1297 } 1298 1299 func (s networkingVNET) Repr() string { 1300 if !s.Valid() { 1301 tokens := strings.SplitN(s.value, "_", 3) 1302 return fmt.Sprintf("VNET{INVALID=%v}", tokens) 1303 } 1304 return fmt.Sprintf("VNET{%d} %s", s.Number(), s.Option()) 1305 } 1306 1307 // Interface name 1308 type networkingInterface struct { 1309 name string 1310 } 1311 1312 func (s networkingInterface) Interface() (*net.Interface, error) { 1313 return net.InterfaceByName(s.name) 1314 } 1315 1316 // networking command entry types 1317 type networkingCommandEntry_answer struct { 1318 vnet networkingVNET 1319 value string 1320 } 1321 type networkingCommandEntry_remove_answer struct { 1322 vnet networkingVNET 1323 } 1324 type networkingCommandEntry_add_nat_portfwd struct { 1325 vnet int 1326 protocol string 1327 port int 1328 target_host net.IP 1329 target_port int 1330 } 1331 type networkingCommandEntry_remove_nat_portfwd struct { 1332 vnet int 1333 protocol string 1334 port int 1335 } 1336 type networkingCommandEntry_add_dhcp_mac_to_ip struct { 1337 vnet int 1338 mac net.HardwareAddr 1339 ip net.IP 1340 } 1341 type networkingCommandEntry_remove_dhcp_mac_to_ip struct { 1342 vnet int 1343 mac net.HardwareAddr 1344 } 1345 type networkingCommandEntry_add_bridge_mapping struct { 1346 intf networkingInterface 1347 vnet int 1348 } 1349 type networkingCommandEntry_remove_bridge_mapping struct { 1350 intf networkingInterface 1351 } 1352 type networkingCommandEntry_add_nat_prefix struct { 1353 vnet int 1354 prefix int 1355 } 1356 type networkingCommandEntry_remove_nat_prefix struct { 1357 vnet int 1358 prefix int 1359 } 1360 1361 type networkingCommandEntry struct { 1362 entry interface{} 1363 answer *networkingCommandEntry_answer 1364 remove_answer *networkingCommandEntry_remove_answer 1365 add_nat_portfwd *networkingCommandEntry_add_nat_portfwd 1366 remove_nat_portfwd *networkingCommandEntry_remove_nat_portfwd 1367 add_dhcp_mac_to_ip *networkingCommandEntry_add_dhcp_mac_to_ip 1368 remove_dhcp_mac_to_ip *networkingCommandEntry_remove_dhcp_mac_to_ip 1369 add_bridge_mapping *networkingCommandEntry_add_bridge_mapping 1370 remove_bridge_mapping *networkingCommandEntry_remove_bridge_mapping 1371 add_nat_prefix *networkingCommandEntry_add_nat_prefix 1372 remove_nat_prefix *networkingCommandEntry_remove_nat_prefix 1373 } 1374 1375 func (e networkingCommandEntry) Name() string { 1376 switch e.entry.(type) { 1377 case networkingCommandEntry_answer: 1378 return "answer" 1379 case networkingCommandEntry_remove_answer: 1380 return "remove_answer" 1381 case networkingCommandEntry_add_nat_portfwd: 1382 return "add_nat_portfwd" 1383 case networkingCommandEntry_remove_nat_portfwd: 1384 return "remove_nat_portfwd" 1385 case networkingCommandEntry_add_dhcp_mac_to_ip: 1386 return "add_dhcp_mac_to_ip" 1387 case networkingCommandEntry_remove_dhcp_mac_to_ip: 1388 return "remove_dhcp_mac_to_ip" 1389 case networkingCommandEntry_add_bridge_mapping: 1390 return "add_bridge_mapping" 1391 case networkingCommandEntry_remove_bridge_mapping: 1392 return "remove_bridge_mapping" 1393 case networkingCommandEntry_add_nat_prefix: 1394 return "add_nat_prefix" 1395 case networkingCommandEntry_remove_nat_prefix: 1396 return "remove_nat_prefix" 1397 } 1398 return "" 1399 } 1400 1401 func (e networkingCommandEntry) Entry() reflect.Value { 1402 this := reflect.ValueOf(e) 1403 switch e.entry.(type) { 1404 case networkingCommandEntry_answer: 1405 return reflect.Indirect(this.FieldByName("answer")) 1406 case networkingCommandEntry_remove_answer: 1407 return reflect.Indirect(this.FieldByName("remove_answer")) 1408 case networkingCommandEntry_add_nat_portfwd: 1409 return reflect.Indirect(this.FieldByName("add_nat_portfwd")) 1410 case networkingCommandEntry_remove_nat_portfwd: 1411 return reflect.Indirect(this.FieldByName("remove_nat_portfwd")) 1412 case networkingCommandEntry_add_dhcp_mac_to_ip: 1413 return reflect.Indirect(this.FieldByName("add_dhcp_mac_to_ip")) 1414 case networkingCommandEntry_remove_dhcp_mac_to_ip: 1415 return reflect.Indirect(this.FieldByName("remove_dhcp_mac_to_ip")) 1416 case networkingCommandEntry_add_bridge_mapping: 1417 return reflect.Indirect(this.FieldByName("add_bridge_mapping")) 1418 case networkingCommandEntry_remove_bridge_mapping: 1419 return reflect.Indirect(this.FieldByName("remove_bridge_mapping")) 1420 case networkingCommandEntry_add_nat_prefix: 1421 return reflect.Indirect(this.FieldByName("add_nat_prefix")) 1422 case networkingCommandEntry_remove_nat_prefix: 1423 return reflect.Indirect(this.FieldByName("remove_nat_prefix")) 1424 } 1425 return reflect.Value{} 1426 } 1427 1428 func (e networkingCommandEntry) Repr() string { 1429 var result map[string]interface{} 1430 result = make(map[string]interface{}) 1431 1432 entryN, entry := e.Name(), e.Entry() 1433 entryT := entry.Type() 1434 for i := 0; i < entry.NumField(); i++ { 1435 fld, fldT := entry.Field(i), entryT.Field(i) 1436 result[fldT.Name] = fld 1437 } 1438 return fmt.Sprintf("%s -> %v", entryN, result) 1439 } 1440 1441 // networking command entry parsers 1442 func parseNetworkingCommand_answer(row []string) (*networkingCommandEntry, error) { 1443 if len(row) != 2 { 1444 return nil, fmt.Errorf("Expected %d arguments. Received only %d.", 2, len(row)) 1445 } 1446 vnet := networkingVNET{value: row[0]} 1447 if !vnet.Valid() { 1448 return nil, fmt.Errorf("Invalid format for VNET.") 1449 } 1450 value := row[1] 1451 1452 result := networkingCommandEntry_answer{vnet: vnet, value: value} 1453 return &networkingCommandEntry{entry: result, answer: &result}, nil 1454 } 1455 func parseNetworkingCommand_remove_answer(row []string) (*networkingCommandEntry, error) { 1456 if len(row) != 1 { 1457 return nil, fmt.Errorf("Expected %d argument. Received %d.", 1, len(row)) 1458 } 1459 vnet := networkingVNET{value: row[0]} 1460 if !vnet.Valid() { 1461 return nil, fmt.Errorf("Invalid format for VNET.") 1462 } 1463 1464 result := networkingCommandEntry_remove_answer{vnet: vnet} 1465 return &networkingCommandEntry{entry: result, remove_answer: &result}, nil 1466 } 1467 func parseNetworkingCommand_add_nat_portfwd(row []string) (*networkingCommandEntry, error) { 1468 if len(row) != 5 { 1469 return nil, fmt.Errorf("Expected %d arguments. Received only %d.", 5, len(row)) 1470 } 1471 1472 vnet, err := strconv.Atoi(row[0]) 1473 if err != nil { 1474 return nil, fmt.Errorf("Unable to parse first argument as an integer. : %v", row[0]) 1475 } 1476 1477 protocol := strings.ToLower(row[1]) 1478 if !(protocol == "tcp" || protocol == "udp") { 1479 return nil, fmt.Errorf("Expected \"tcp\" or \"udp\" for second argument. : %v", row[1]) 1480 } 1481 1482 sport, err := strconv.Atoi(row[2]) 1483 if err != nil { 1484 return nil, fmt.Errorf("Unable to parse third argument as an integer. : %v", row[2]) 1485 } 1486 1487 dest := net.ParseIP(row[3]) 1488 if dest == nil { 1489 return nil, fmt.Errorf("Unable to parse fourth argument as an IPv4 address. : %v", row[2]) 1490 } 1491 1492 dport, err := strconv.Atoi(row[4]) 1493 if err != nil { 1494 return nil, fmt.Errorf("Unable to parse fifth argument as an integer. : %v", row[4]) 1495 } 1496 1497 result := networkingCommandEntry_add_nat_portfwd{vnet: vnet - 1, protocol: protocol, port: sport, target_host: dest, target_port: dport} 1498 return &networkingCommandEntry{entry: result, add_nat_portfwd: &result}, nil 1499 } 1500 func parseNetworkingCommand_remove_nat_portfwd(row []string) (*networkingCommandEntry, error) { 1501 if len(row) != 3 { 1502 return nil, fmt.Errorf("Expected %d arguments. Received only %d.", 3, len(row)) 1503 } 1504 1505 vnet, err := strconv.Atoi(row[0]) 1506 if err != nil { 1507 return nil, fmt.Errorf("Unable to parse first argument as an integer. : %v", row[0]) 1508 } 1509 1510 protocol := strings.ToLower(row[1]) 1511 if !(protocol == "tcp" || protocol == "udp") { 1512 return nil, fmt.Errorf("Expected \"tcp\" or \"udp\" for second argument. : %v", row[1]) 1513 } 1514 1515 sport, err := strconv.Atoi(row[2]) 1516 if err != nil { 1517 return nil, fmt.Errorf("Unable to parse third argument as an integer. : %v", row[2]) 1518 } 1519 1520 result := networkingCommandEntry_remove_nat_portfwd{vnet: vnet - 1, protocol: protocol, port: sport} 1521 return &networkingCommandEntry{entry: result, remove_nat_portfwd: &result}, nil 1522 } 1523 func parseNetworkingCommand_add_dhcp_mac_to_ip(row []string) (*networkingCommandEntry, error) { 1524 if len(row) != 3 { 1525 return nil, fmt.Errorf("Expected %d arguments. Received only %d.", 3, len(row)) 1526 } 1527 1528 vnet, err := strconv.Atoi(row[0]) 1529 if err != nil { 1530 return nil, fmt.Errorf("Unable to parse first argument as an integer. : %v", row[0]) 1531 } 1532 1533 mac, err := net.ParseMAC(row[1]) 1534 if err != nil { 1535 return nil, fmt.Errorf("Unable to parse second argument as hwaddr. : %v", row[1]) 1536 } 1537 1538 ip := net.ParseIP(row[2]) 1539 if ip != nil { 1540 return nil, fmt.Errorf("Unable to parse third argument as ipv4. : %v", row[2]) 1541 } 1542 1543 result := networkingCommandEntry_add_dhcp_mac_to_ip{vnet: vnet - 1, mac: mac, ip: ip} 1544 return &networkingCommandEntry{entry: result, add_dhcp_mac_to_ip: &result}, nil 1545 } 1546 func parseNetworkingCommand_remove_dhcp_mac_to_ip(row []string) (*networkingCommandEntry, error) { 1547 if len(row) != 2 { 1548 return nil, fmt.Errorf("Expected %d arguments. Received only %d.", 2, len(row)) 1549 } 1550 1551 vnet, err := strconv.Atoi(row[0]) 1552 if err != nil { 1553 return nil, fmt.Errorf("Unable to parse first argument as an integer. : %v", row[0]) 1554 } 1555 1556 mac, err := net.ParseMAC(row[1]) 1557 if err != nil { 1558 return nil, fmt.Errorf("Unable to parse second argument as hwaddr. : %v", row[1]) 1559 } 1560 1561 result := networkingCommandEntry_remove_dhcp_mac_to_ip{vnet: vnet - 1, mac: mac} 1562 return &networkingCommandEntry{entry: result, remove_dhcp_mac_to_ip: &result}, nil 1563 } 1564 func parseNetworkingCommand_add_bridge_mapping(row []string) (*networkingCommandEntry, error) { 1565 if len(row) != 2 { 1566 return nil, fmt.Errorf("Expected %d arguments. Received only %d.", 2, len(row)) 1567 } 1568 intf := networkingInterface{name: row[0]} 1569 1570 vnet, err := strconv.Atoi(row[1]) 1571 if err != nil { 1572 return nil, fmt.Errorf("Unable to parse second argument as an integer. : %v", row[2]) 1573 } 1574 1575 result := networkingCommandEntry_add_bridge_mapping{intf: intf, vnet: vnet - 1} 1576 return &networkingCommandEntry{entry: result, add_bridge_mapping: &result}, nil 1577 } 1578 func parseNetworkingCommand_remove_bridge_mapping(row []string) (*networkingCommandEntry, error) { 1579 if len(row) != 1 { 1580 return nil, fmt.Errorf("Expected %d argument. Received %d.", 1, len(row)) 1581 } 1582 intf := networkingInterface{name: row[0]} 1583 /* 1584 number, err := strconv.Atoi(row[0]) 1585 if err != nil { 1586 return nil, fmt.Errorf("Unable to parse first argument as an integer. : %v", row[0]) 1587 } 1588 */ 1589 result := networkingCommandEntry_remove_bridge_mapping{intf: intf} 1590 return &networkingCommandEntry{entry: result, remove_bridge_mapping: &result}, nil 1591 } 1592 func parseNetworkingCommand_add_nat_prefix(row []string) (*networkingCommandEntry, error) { 1593 if len(row) != 2 { 1594 return nil, fmt.Errorf("Expected %d arguments. Received only %d.", 2, len(row)) 1595 } 1596 1597 vnet, err := strconv.Atoi(row[0]) 1598 if err != nil { 1599 return nil, fmt.Errorf("Unable to parse first argument as an integer. : %v", row[0]) 1600 } 1601 1602 if !strings.HasPrefix(row[1], "/") { 1603 return nil, fmt.Errorf("Expected second argument to begin with \"/\". : %v", row[1]) 1604 } 1605 1606 prefix, err := strconv.Atoi(row[1][1:]) 1607 if err != nil { 1608 return nil, fmt.Errorf("Unable to parse prefix out of second argument. : %v", row[1]) 1609 } 1610 1611 result := networkingCommandEntry_add_nat_prefix{vnet: vnet - 1, prefix: prefix} 1612 return &networkingCommandEntry{entry: result, add_nat_prefix: &result}, nil 1613 } 1614 func parseNetworkingCommand_remove_nat_prefix(row []string) (*networkingCommandEntry, error) { 1615 if len(row) != 2 { 1616 return nil, fmt.Errorf("Expected %d arguments. Received only %d.", 2, len(row)) 1617 } 1618 1619 vnet, err := strconv.Atoi(row[0]) 1620 if err != nil { 1621 return nil, fmt.Errorf("Unable to parse first argument as an integer. : %v", row[0]) 1622 } 1623 1624 if !strings.HasPrefix(row[1], "/") { 1625 return nil, fmt.Errorf("Expected second argument to begin with \"/\". : %v", row[1]) 1626 } 1627 prefix, err := strconv.Atoi(row[1][1:]) 1628 if err != nil { 1629 return nil, fmt.Errorf("Unable to parse prefix out of second argument. : %v", row[1]) 1630 } 1631 1632 result := networkingCommandEntry_remove_nat_prefix{vnet: vnet - 1, prefix: prefix} 1633 return &networkingCommandEntry{entry: result, remove_nat_prefix: &result}, nil 1634 } 1635 1636 type networkingCommandParser struct { 1637 command string 1638 callback func([]string) (*networkingCommandEntry, error) 1639 } 1640 1641 var NetworkingCommandParsers = []networkingCommandParser{ 1642 /* DictRecordParseFunct */ {command: "answer", callback: parseNetworkingCommand_answer}, 1643 /* DictRecordParseFunct */ {command: "remove_answer", callback: parseNetworkingCommand_remove_answer}, 1644 /* NatFwdRecordParseFunct */ {command: "add_nat_portfwd", callback: parseNetworkingCommand_add_nat_portfwd}, 1645 /* NatFwdRecordParseFunct */ {command: "remove_nat_portfwd", callback: parseNetworkingCommand_remove_nat_portfwd}, 1646 /* DhcpMacRecordParseFunct */ {command: "add_dhcp_mac_to_ip", callback: parseNetworkingCommand_add_dhcp_mac_to_ip}, 1647 /* DhcpMacRecordParseFunct */ {command: "remove_dhcp_mac_to_ip", callback: parseNetworkingCommand_remove_dhcp_mac_to_ip}, 1648 /* BridgeMappingRecordParseFunct */ {command: "add_bridge_mapping", callback: parseNetworkingCommand_add_bridge_mapping}, 1649 /* BridgeMappingRecordParseFunct */ {command: "remove_bridge_mapping", callback: parseNetworkingCommand_remove_bridge_mapping}, 1650 /* NatPrefixRecordParseFunct */ {command: "add_nat_prefix", callback: parseNetworkingCommand_add_nat_prefix}, 1651 /* NatPrefixRecordParseFunct */ {command: "remove_nat_prefix", callback: parseNetworkingCommand_remove_nat_prefix}, 1652 } 1653 1654 func NetworkingParserByCommand(command string) *func([]string) (*networkingCommandEntry, error) { 1655 for _, p := range NetworkingCommandParsers { 1656 if p.command == command { 1657 return &p.callback 1658 } 1659 } 1660 return nil 1661 } 1662 1663 func parseNetworkingConfig(eof sentinelSignaller, rows chan []string) (chan networkingCommandEntry, sentinelSignaller) { 1664 var out chan networkingCommandEntry 1665 1666 eop := make(sentinelSignaller) 1667 1668 out = make(chan networkingCommandEntry) 1669 go func(in chan []string, out chan networkingCommandEntry) { 1670 for reading := true; reading; { 1671 select { 1672 case <-eof: 1673 reading = false 1674 case row := <-in: 1675 if len(row) >= 1 { 1676 parser := NetworkingParserByCommand(row[0]) 1677 if parser == nil { 1678 log.Printf("Invalid command : %v", row) 1679 continue 1680 } 1681 callback := *parser 1682 entry, err := callback(row[1:]) 1683 if err != nil { 1684 log.Printf("Unable to parse command : %v %v", err, row) 1685 continue 1686 } 1687 out <- *entry 1688 } 1689 } 1690 } 1691 close(eop) 1692 }(rows, out) 1693 return out, eop 1694 } 1695 1696 type NetworkingConfig struct { 1697 answer map[int]map[string]string 1698 nat_portfwd map[int]map[string]string 1699 dhcp_mac_to_ip map[int]map[string]net.IP 1700 //bridge_mapping map[net.Interface]uint64 // XXX: we don't need the actual interface for anything but informing the user. 1701 bridge_mapping map[string]int 1702 nat_prefix map[int][]int 1703 } 1704 1705 func (c NetworkingConfig) repr() string { 1706 return fmt.Sprintf("answer -> %v\nnat_portfwd -> %v\ndhcp_mac_to_ip -> %v\nbridge_mapping -> %v\nnat_prefix -> %v", c.answer, c.nat_portfwd, c.dhcp_mac_to_ip, c.bridge_mapping, c.nat_prefix) 1707 } 1708 1709 func flattenNetworkingConfig(eof sentinelSignaller, in chan networkingCommandEntry) NetworkingConfig { 1710 var result NetworkingConfig 1711 var vmnet int 1712 1713 result.answer = make(map[int]map[string]string) 1714 result.nat_portfwd = make(map[int]map[string]string) 1715 result.dhcp_mac_to_ip = make(map[int]map[string]net.IP) 1716 result.bridge_mapping = make(map[string]int) 1717 result.nat_prefix = make(map[int][]int) 1718 1719 for reading := true; reading; { 1720 select { 1721 case <-eof: 1722 reading = false 1723 case e := <-in: 1724 switch e.entry.(type) { 1725 case networkingCommandEntry_answer: 1726 vnet := e.answer.vnet 1727 answers, exists := result.answer[vnet.Number()] 1728 if !exists { 1729 answers = make(map[string]string) 1730 result.answer[vnet.Number()] = answers 1731 } 1732 answers[vnet.Option()] = e.answer.value 1733 case networkingCommandEntry_remove_answer: 1734 vnet := e.remove_answer.vnet 1735 answers, exists := result.answer[vnet.Number()] 1736 if exists { 1737 delete(answers, vnet.Option()) 1738 } else { 1739 log.Printf("Unable to remove answer %s as specified by `remove_answer`.\n", vnet.Repr()) 1740 } 1741 case networkingCommandEntry_add_nat_portfwd: 1742 vmnet = e.add_nat_portfwd.vnet 1743 protoport := fmt.Sprintf("%s/%d", e.add_nat_portfwd.protocol, e.add_nat_portfwd.port) 1744 target := fmt.Sprintf("%s:%d", e.add_nat_portfwd.target_host, e.add_nat_portfwd.target_port) 1745 portfwds, exists := result.nat_portfwd[vmnet] 1746 if !exists { 1747 portfwds = make(map[string]string) 1748 result.nat_portfwd[vmnet] = portfwds 1749 } 1750 portfwds[protoport] = target 1751 case networkingCommandEntry_remove_nat_portfwd: 1752 vmnet = e.remove_nat_portfwd.vnet 1753 protoport := fmt.Sprintf("%s/%d", e.remove_nat_portfwd.protocol, e.remove_nat_portfwd.port) 1754 portfwds, exists := result.nat_portfwd[vmnet] 1755 if exists { 1756 delete(portfwds, protoport) 1757 } else { 1758 log.Printf("Unable to remove nat port-forward %s from interface %s%d as requested by `remove_nat_portfwd`.\n", protoport, NetworkingInterfacePrefix, vmnet) 1759 } 1760 case networkingCommandEntry_add_dhcp_mac_to_ip: 1761 vmnet = e.add_dhcp_mac_to_ip.vnet 1762 dhcpmacs, exists := result.dhcp_mac_to_ip[vmnet] 1763 if !exists { 1764 dhcpmacs = make(map[string]net.IP) 1765 result.dhcp_mac_to_ip[vmnet] = dhcpmacs 1766 } 1767 dhcpmacs[e.add_dhcp_mac_to_ip.mac.String()] = e.add_dhcp_mac_to_ip.ip 1768 case networkingCommandEntry_remove_dhcp_mac_to_ip: 1769 vmnet = e.remove_dhcp_mac_to_ip.vnet 1770 dhcpmacs, exists := result.dhcp_mac_to_ip[vmnet] 1771 if exists { 1772 delete(dhcpmacs, e.remove_dhcp_mac_to_ip.mac.String()) 1773 } else { 1774 log.Printf("Unable to remove dhcp_mac_to_ip entry %v from interface %s%d as specified by `remove_dhcp_mac_to_ip`.\n", e.remove_dhcp_mac_to_ip, NetworkingInterfacePrefix, vmnet) 1775 } 1776 case networkingCommandEntry_add_bridge_mapping: 1777 intf := e.add_bridge_mapping.intf 1778 if _, err := intf.Interface(); err != nil { 1779 log.Printf("Interface \"%s\" as specified by `add_bridge_mapping` was not found on the current platform. This is a non-critical error. Ignoring.", intf.name) 1780 } 1781 result.bridge_mapping[intf.name] = e.add_bridge_mapping.vnet 1782 case networkingCommandEntry_remove_bridge_mapping: 1783 intf := e.remove_bridge_mapping.intf 1784 if _, err := intf.Interface(); err != nil { 1785 log.Printf("Interface \"%s\" as specified by `remove_bridge_mapping` was not found on the current platform. This is a non-critical error. Ignoring.", intf.name) 1786 } 1787 delete(result.bridge_mapping, intf.name) 1788 case networkingCommandEntry_add_nat_prefix: 1789 vmnet = e.add_nat_prefix.vnet 1790 _, exists := result.nat_prefix[vmnet] 1791 if exists { 1792 result.nat_prefix[vmnet] = append(result.nat_prefix[vmnet], e.add_nat_prefix.prefix) 1793 } else { 1794 result.nat_prefix[vmnet] = []int{e.add_nat_prefix.prefix} 1795 } 1796 case networkingCommandEntry_remove_nat_prefix: 1797 vmnet = e.remove_nat_prefix.vnet 1798 prefixes, exists := result.nat_prefix[vmnet] 1799 if exists { 1800 for index := 0; index < len(prefixes); index++ { 1801 if prefixes[index] == e.remove_nat_prefix.prefix { 1802 result.nat_prefix[vmnet] = append(prefixes[:index], prefixes[index+1:]...) 1803 break 1804 } 1805 } 1806 } else { 1807 log.Printf("Unable to remove nat prefix /%d from interface %s%d as specified by `remove_nat_prefix`.\n", e.remove_nat_prefix.prefix, NetworkingInterfacePrefix, vmnet) 1808 } 1809 } 1810 } 1811 } 1812 return result 1813 } 1814 1815 // Constructor for networking file 1816 func ReadNetworkingConfig(fd *os.File) (NetworkingConfig, error) { 1817 // start piecing together different parts of the file 1818 fromfile, eof := consumeFile(fd) 1819 tokenized, eot := tokenizeNetworkingConfig(eof, fromfile) 1820 rows, eos := splitNetworkingConfig(eot, tokenized) 1821 entries, eop := parseNetworkingConfig(eos, rows) 1822 1823 // parse the version 1824 parsed_version, err := networkingReadVersion(<-rows) 1825 if err != nil { 1826 return NetworkingConfig{}, err 1827 } 1828 1829 // verify that it's 1.0 since that's all we support. 1830 version := parsed_version.Number() 1831 if version != 1.0 { 1832 return NetworkingConfig{}, fmt.Errorf("Expected version %f of networking file. Received version %f.", 1.0, version) 1833 } 1834 1835 // convert to a configuration 1836 result := flattenNetworkingConfig(eop, entries) 1837 return result, nil 1838 } 1839 1840 // netmapper interface 1841 type NetworkingType int 1842 1843 const ( 1844 NetworkingType_HOSTONLY = iota + 1 1845 NetworkingType_NAT 1846 NetworkingType_BRIDGED 1847 ) 1848 1849 func networkingConfig_InterfaceTypes(config NetworkingConfig) map[int]NetworkingType { 1850 var result map[int]NetworkingType 1851 result = make(map[int]NetworkingType) 1852 1853 // defaults 1854 result[0] = NetworkingType_BRIDGED 1855 result[1] = NetworkingType_HOSTONLY 1856 result[8] = NetworkingType_NAT 1857 1858 // walk through config collecting bridged interfaces 1859 for _, vmnet := range config.bridge_mapping { 1860 result[vmnet] = NetworkingType_BRIDGED 1861 } 1862 1863 // walk through answers finding out which ones are nat versus hostonly 1864 for vmnet, table := range config.answer { 1865 // everything should be defined as a virtual adapter... 1866 if table["VIRTUAL_ADAPTER"] == "yes" { 1867 1868 // validate that the VNET entry contains everything we expect it to 1869 _, subnetQ := table["HOSTONLY_SUBNET"] 1870 _, netmaskQ := table["HOSTONLY_NETMASK"] 1871 if !(subnetQ && netmaskQ) { 1872 log.Printf("Interface %s%d is missing some expected keys (HOSTONLY_SUBNET, HOSTONLY_NETMASK). This is non-critical. Ignoring..", NetworkingInterfacePrefix, vmnet) 1873 } 1874 1875 // distinguish between nat or hostonly 1876 if table["NAT"] == "yes" { 1877 result[vmnet] = NetworkingType_NAT 1878 } else { 1879 result[vmnet] = NetworkingType_HOSTONLY 1880 } 1881 1882 // if it's not a virtual_adapter, then it must be an alias (really a bridge). 1883 } else { 1884 result[vmnet] = NetworkingType_BRIDGED 1885 } 1886 } 1887 return result 1888 } 1889 1890 func networkingConfig_NamesToVmnet(config NetworkingConfig) map[NetworkingType][]int { 1891 types := networkingConfig_InterfaceTypes(config) 1892 1893 // now sort the keys 1894 var keys []int 1895 for vmnet := range types { 1896 keys = append(keys, vmnet) 1897 } 1898 sort.Ints(keys) 1899 1900 // build result dictionary 1901 var result map[NetworkingType][]int 1902 result = make(map[NetworkingType][]int) 1903 for i := 0; i < len(keys); i++ { 1904 t := types[keys[i]] 1905 result[t] = append(result[t], keys[i]) 1906 } 1907 return result 1908 } 1909 1910 const NetworkingInterfacePrefix = "vmnet" 1911 1912 func (e NetworkingConfig) NameIntoDevices(name string) ([]string, error) { 1913 netmapper := networkingConfig_NamesToVmnet(e) 1914 name = strings.ToLower(name) 1915 1916 var vmnets []string 1917 var networkingType NetworkingType 1918 if name == "hostonly" && len(netmapper[NetworkingType_HOSTONLY]) > 0 { 1919 networkingType = NetworkingType_HOSTONLY 1920 } else if name == "nat" && len(netmapper[NetworkingType_NAT]) > 0 { 1921 networkingType = NetworkingType_NAT 1922 } else if name == "bridged" && len(netmapper[NetworkingType_BRIDGED]) > 0 { 1923 networkingType = NetworkingType_BRIDGED 1924 } else { 1925 return make([]string, 0), fmt.Errorf("Network name not found: %v", name) 1926 } 1927 1928 for i := 0; i < len(netmapper[networkingType]); i++ { 1929 vmnets = append(vmnets, fmt.Sprintf("%s%d", NetworkingInterfacePrefix, netmapper[networkingType][i])) 1930 } 1931 return vmnets, nil 1932 } 1933 1934 func (e NetworkingConfig) DeviceIntoName(device string) (string, error) { 1935 types := networkingConfig_InterfaceTypes(e) 1936 1937 lowerdevice := strings.ToLower(device) 1938 if !strings.HasPrefix(lowerdevice, NetworkingInterfacePrefix) { 1939 return device, nil 1940 } 1941 vmnet, err := strconv.Atoi(lowerdevice[len(NetworkingInterfacePrefix):]) 1942 if err != nil { 1943 return "", err 1944 } 1945 network := types[vmnet] 1946 switch network { 1947 case NetworkingType_HOSTONLY: 1948 return "hostonly", nil 1949 case NetworkingType_NAT: 1950 return "nat", nil 1951 case NetworkingType_BRIDGED: 1952 return "bridged", nil 1953 } 1954 return "", fmt.Errorf("Unable to determine network type for device %s%d.", NetworkingInterfacePrefix, vmnet) 1955 } 1956 1957 /** generic async file reader */ 1958 func consumeFile(fd *os.File) (chan byte, sentinelSignaller) { 1959 fromfile := make(chan byte) 1960 eof := make(sentinelSignaller) 1961 go func() { 1962 b := make([]byte, 1) 1963 for { 1964 _, err := fd.Read(b) 1965 if err == io.EOF { 1966 break 1967 } 1968 fromfile <- b[0] 1969 } 1970 close(eof) 1971 }() 1972 return fromfile, eof 1973 }