// 2019 Rackspace, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"): you may // not use this file except in compliance with the License. You may obtain // a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations // under the License. package tsip import ( "errors" "net" "github.rackspace.com/gorax/clients/coreAPI" "github.rackspace.com/gorax/clients/dcxSwitchapi" "github.rackspace.com/gorax/clients/goctk" "github.rackspace.com/gorax/clients/unipede" "github.rackspace.com/gorax/tools/passkey" ) var ( privateIPBlocks []*net.IPNet errNoXlate = errors.New("no translation exist for address") errConnect = errors.New("unable to connect to edge device") errGather = errors.New("unable to gather data from edge device") errNotRoutable = errors.New("requested IP address is not a Rackspace global routable address") errNoNextHop = errors.New("cannot find the next-hop address of requested IP") errUnsupported = errors.New("next-hop device is current not supported for true-source IP lookups") ) type ( // Client type represents client references to third-party resources required // for the methods within this package. // swagger:ignore Client struct { ctk *goctk.Client u *unipede.Client fe *dcxSwitchapi.Client core *coreAPI.Client } // RealIP type will represent the return data for a IP lookup of a // publicly routed address. // // swagger:model RealIP struct { MappedAddress string `json:"mapped_address"` RealAddress []string `json:"real_address"` XlateType string `json:"xlate_type"` Gateway deviceInfo `json:"gateway,omitempty"` Device deviceInfo `json:"device"` Error []string `json:"errors,omitempty"` Details string `json:"details,omitempty"` port string `json:"-"` } deviceInfo struct { ID int `json:"id"` Platform string `json:"platform"` Address string `json:"ip_address"` DC string `json:"data_center"` Status string `json:"status"` Name string `json:"name"` addrObj net.IP `json:"-"` } ) func init() { for _, cidr := range []string{ "127.0.0.0/8", // IPv4 loopback "10.128.0.0/9", // RFC1918 excluding RAX public 10dot "172.16.0.0/12", // RFC1918 "192.168.0.0/16", // RFC1918 } { _, block, _ := net.ParseCIDR(cidr) privateIPBlocks = append(privateIPBlocks, block) } } // New function will take individual clients to manually create a Client type. func New(ctk *goctk.Client, u *unipede.Client, fe *dcxSwitchapi.Client, core *coreAPI.Client) *Client { return &Client{ctk: ctk, u: u, fe: fe, core: core} } // NewClient function will take a initialized passkey client to create a Client type. func NewClient(p *passkey.Client) (*Client, error) { core, err := coreAPI.ServiceToken(p.Keys.ServiceTokens.Credential.Password) if err != nil { return nil, err } u, err := unipede.New(p.Service.SSO.Credential.Username, p.Service.SSO.Credential.Password, "") if err != nil { return nil, err } fe, err := dcxSwitchapi.NewClient(p.Service.SSO.Credential.Username, p.Service.SSO.Credential.Password) if err != nil { return nil, err } ctk, err := goctk.New(p.Service.SSO.Credential.Username, p.Service.SSO.Credential.Password, false) if err != nil { return nil, err } return &Client{ctk: ctk, u: u, fe: fe, core: core}, nil } // existInSlice is a small helper function to determine if a string is part of // a list of strings. func existInSlice(elem string, slice []string) bool { for _, i := range slice { if elem == i { return true } } return false } // isPrivateIP is a small helper func to determine if the passed in // IP type is a private RFC 1918 (by Rackspace standards) address. func isPrivateIP(ip net.IP) bool { for _, block := range privateIPBlocks { if block.Contains(ip) { return true } } return false }