// 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 ( "net" "net/http" "strings" "github.com/sirupsen/logrus" ) // GetRealIP method will take a ip address as a string input and perform a subsequent methods // to find the next-hop address, perform a lookup, and attempt to gather the real (possibly NAT'd) // information of the passed in IP. // // Return data will be the real-address of the passed in address. func (c *Client) GetRealIP(ipAddr net.IP, port string) (r *RealIP, code int, err error) { r = new(RealIP) // Fetch device data for the IP of the passed in device from CTK API self, err := c.ctk.IPAssignment(ipAddr.String()) r = &RealIP{ MappedAddress: ipAddr.String(), port: port, Device: deviceInfo{ ID: self.DeviceID, Platform: self.PlatformModel, Address: ipAddr.String(), DC: self.DC, Status: self.Status, Name: self.Name, addrObj: ipAddr, }, } if err != nil { logrus.Errorf("%s:GetRealIP:Self:IPAssignment:%s", r.MappedAddress, err) r.Error = append(r.Error, err.Error()) } if isPrivateIP(net.ParseIP(r.MappedAddress)) { r.RealAddress = []string{r.MappedAddress} return r, http.StatusBadRequest, errNotRoutable } // Pull the next-hop address of the passed in IP nextHopAddr, err := c.FindNextHop(r.MappedAddress) if err != nil { logrus.Errorf("%s:GetRealIP:FindNextHop:%s", r.MappedAddress, err) return r, http.StatusNotFound, errNoNextHop } // Fetch device data for the next-hop address from CTK API gw, err := c.ctk.IPAssignment(nextHopAddr) if err != nil { logrus.Errorf("%s:GetRealIP:GW:IPAssignment:%s", r.MappedAddress, err) return r, http.StatusBadGateway, err } r.Gateway = deviceInfo{ ID: gw.DeviceID, Platform: gw.PlatformModel, Address: nextHopAddr, DC: gw.DC, Status: gw.Status, Name: gw.Name, addrObj: net.ParseIP(nextHopAddr), } logrus.Infof("GetRealIP:found next-hop %s [%d %s]", r.Gateway.Address, r.Gateway.ID, r.Gateway.Platform) switch platform := strings.ToLower(r.Gateway.Platform); { case strings.Contains(platform, "cisco asa"): if err := c.lookupASA(r); err != nil { return r, http.StatusBadGateway, err } return r, http.StatusOK, nil case strings.Contains(platform, "bigip"): if err := c.lookupF5(r); err != nil { return r, http.StatusBadGateway, err } return r, http.StatusOK, nil default: logrus.Errorf("%s:GetRealIP:UnsupportedPlatform:%s", r.MappedAddress, platform) return r, http.StatusNotImplemented, errUnsupported } }