1bf83f301SIdo Barnea#ifndef UTL_IP_H
2bf83f301SIdo Barnea#define UTL_IP_H
3bf83f301SIdo Barnea/*
4bf83f301SIdo Barnea Cisco Systems, Inc.
5bf83f301SIdo Barnea*/
6bf83f301SIdo Barnea
7bf83f301SIdo Barnea/*
8bf83f301SIdo BarneaCopyright (c) 2016-2016 Cisco Systems, Inc.
9bf83f301SIdo Barnea
10bf83f301SIdo BarneaLicensed under the Apache License, Version 2.0 (the "License");
11bf83f301SIdo Barneayou may not use this file except in compliance with the License.
12bf83f301SIdo BarneaYou may obtain a copy of the License at
13bf83f301SIdo Barnea
14bf83f301SIdo Barnea    http://www.apache.org/licenses/LICENSE-2.0
15bf83f301SIdo Barnea
16bf83f301SIdo BarneaUnless required by applicable law or agreed to in writing, software
17bf83f301SIdo Barneadistributed under the License is distributed on an "AS IS" BASIS,
18bf83f301SIdo BarneaWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19bf83f301SIdo BarneaSee the License for the specific language governing permissions and
20bf83f301SIdo Barnealimitations under the License.
21bf83f301SIdo Barnea*/
22bf83f301SIdo Barnea#include <map>
23bf83f301SIdo Barnea#include <sys/socket.h>
24bf83f301SIdo Barnea#include <netinet/in.h>
25bf83f301SIdo Barnea#include <arpa/inet.h>
26bf83f301SIdo Barnea#include "common/basic_utils.h"
27bf83f301SIdo Barnea#include "common/Network/Packet/CPktCmn.h"
28bf83f301SIdo Barnea#include "common/Network/Packet/MacAddress.h"
29bf83f301SIdo Barnea
30bf83f301SIdo Barnea/* IP address, last 32-bits of IPv6 remaps IPv4 */
31bf83f301SIdo Barneatypedef struct {
32bf83f301SIdo Barnea    uint16_t v6[6];  /* First 96-bits of IPv6 */
33bf83f301SIdo Barnea    uint32_t v4;  /* Last 32-bits IPv6 overloads v4 */
34bf83f301SIdo Barnea} ipaddr_t;
35bf83f301SIdo Barnea
36bf83f301SIdo Barnea// Routine to create IPv4 address string
37bf83f301SIdo Barneainline int ip_to_str(uint32_t ip,char * str) {
38bf83f301SIdo Barnea    uint32_t ipv4 = PKT_HTONL(ip);
39bf83f301SIdo Barnea    inet_ntop(AF_INET, (const char *)&ipv4, str, INET_ADDRSTRLEN);
40bf83f301SIdo Barnea    return(strlen(str));
41bf83f301SIdo Barnea}
42bf83f301SIdo Barnea
43bf83f301SIdo Barneainline std::string ip_to_str(uint32_t ip) {
44bf83f301SIdo Barnea    char tmp[INET_ADDRSTRLEN];
45bf83f301SIdo Barnea    ip_to_str(ip, tmp);
46bf83f301SIdo Barnea    return tmp;
47bf83f301SIdo Barnea}
48bf83f301SIdo Barnea
49bf83f301SIdo Barnea// Routine to create IPv6 address string
50bf83f301SIdo Barneainline int ipv6_to_str(ipaddr_t *ip, char * str) {
51bf83f301SIdo Barnea    int idx=0;
52bf83f301SIdo Barnea    uint16_t ipv6[8];
53bf83f301SIdo Barnea    for (uint8_t i=0; i<6; i++) {
54bf83f301SIdo Barnea        ipv6[i] = PKT_HTONS(ip->v6[i]);
55bf83f301SIdo Barnea    }
56bf83f301SIdo Barnea    uint32_t ipv4 = PKT_HTONL(ip->v4);
57bf83f301SIdo Barnea    ipv6[6] = ipv4 & 0xffff;
58bf83f301SIdo Barnea    ipv6[7] = ipv4 >> 16;
59bf83f301SIdo Barnea
60bf83f301SIdo Barnea    str[idx++] = '[';
61bf83f301SIdo Barnea    inet_ntop(AF_INET6, (const char *)&ipv6, &str[1], INET6_ADDRSTRLEN);
62bf83f301SIdo Barnea    idx = strlen(str);
63bf83f301SIdo Barnea    str[idx++] = ']';
64bf83f301SIdo Barnea    str[idx] = 0;
65bf83f301SIdo Barnea    return(idx);
66bf83f301SIdo Barnea}
67bf83f301SIdo Barnea
68bf83f301SIdo Barneainline std::string ip_to_str(uint8_t *ip) {
69bf83f301SIdo Barnea    char tmp[INET6_ADDRSTRLEN];
70bf83f301SIdo Barnea    ipv6_to_str((ipaddr_t *)ip, tmp);
71bf83f301SIdo Barnea    return tmp;
72bf83f301SIdo Barnea}
73bf83f301SIdo Barnea
744a2d56b6SIdo Barneaclass CIpVlan {
754a2d56b6SIdo Barnea    // to be able to use this in map
764a2d56b6SIdo Barnea    friend bool operator<(const CIpVlan& l, const CIpVlan& r) {
774a2d56b6SIdo Barnea        if (l.get_ip() == r.get_ip()) {
784a2d56b6SIdo Barnea            return l.get_vlan() < r.get_vlan();
794a2d56b6SIdo Barnea        } else {
804a2d56b6SIdo Barnea            return l.get_ip() < r.get_ip();
814a2d56b6SIdo Barnea        }
824a2d56b6SIdo Barnea    }
834a2d56b6SIdo Barnea
844a2d56b6SIdo Barnea public:
854a2d56b6SIdo Barnea    CIpVlan(uint32_t ip, uint16_t vlan) {
864a2d56b6SIdo Barnea        m_ip = ip;
874a2d56b6SIdo Barnea        m_vlan = vlan;
884a2d56b6SIdo Barnea    }
894a2d56b6SIdo Barnea    uint16_t get_vlan() const {return m_vlan;}
904a2d56b6SIdo Barnea    void set_vlan(uint16_t vlan) {m_vlan = vlan;}
914a2d56b6SIdo Barnea    uint16_t get_ip() const {return m_ip;}
924a2d56b6SIdo Barnea    void set_ip(uint32_t ip) {m_ip = ip;}
934a2d56b6SIdo Barnea
944a2d56b6SIdo Barnea private:
954a2d56b6SIdo Barnea    uint32_t m_ip;
964a2d56b6SIdo Barnea    uint16_t m_vlan;
974a2d56b6SIdo Barnea};
984a2d56b6SIdo Barnea
994a2d56b6SIdo Barnea
100bf83f301SIdo Barneaclass COneIPInfo {
101bf83f301SIdo Barnea public:
102bf83f301SIdo Barnea    enum {
103bf83f301SIdo Barnea        IP4_VER=4,
104bf83f301SIdo Barnea        IP6_VER=6,
105bf83f301SIdo Barnea    } COneIPInfo_ip_types;
106bf83f301SIdo Barnea
107bf83f301SIdo Barnea public:
1083beb0705SIdo Barnea    virtual ~COneIPInfo() {}
109bf83f301SIdo Barnea    virtual void get_mac(uint8_t *mac) const {
110bf83f301SIdo Barnea        m_mac.copyToArray(mac);
111bf83f301SIdo Barnea    }
112bf83f301SIdo Barnea    virtual void set_mac(uint8_t *mac) {
113bf83f301SIdo Barnea        m_mac.set(mac);
114bf83f301SIdo Barnea    }
115bf83f301SIdo Barnea    uint16_t get_vlan() const {return m_vlan;}
116bf83f301SIdo Barnea    uint16_t get_port() const {return m_port;}
1174c8363eaSIdo Barnea    void set_port(uint8_t port) {m_port = port;}
118bf83f301SIdo Barnea    virtual void dump(FILE *fd) const {
119bf83f301SIdo Barnea        dump(fd, "");
1204a2d56b6SIdo Barnea    }
121bf83f301SIdo Barnea    virtual void dump(FILE *fd, const char *offset) const;
122bf83f301SIdo Barnea    virtual uint8_t ip_ver() const {return 0;}
123bf83f301SIdo Barnea    virtual uint32_t get_arp_req_len() const=0;
124bf83f301SIdo Barnea    virtual uint32_t get_grat_arp_len() const=0;
125bf83f301SIdo Barnea    virtual void fill_arp_req_buf(uint8_t *p, uint16_t port_id, COneIPInfo *sip)=0;
126bf83f301SIdo Barnea    virtual void fill_grat_arp_buf(uint8_t *p)=0;
127bf83f301SIdo Barnea    virtual bool resolve_needed() const;
128bf83f301SIdo Barnea
129bf83f301SIdo Barnea protected:
130bf83f301SIdo Barnea    COneIPInfo(uint16_t vlan, MacAddress mac, uint8_t port) : m_mac(mac) {
131bf83f301SIdo Barnea        m_vlan = vlan;
132bf83f301SIdo Barnea        m_port = port;
133bf83f301SIdo Barnea    }
134bf83f301SIdo Barnea    COneIPInfo(uint16_t vlan, MacAddress mac) : COneIPInfo(vlan, mac, UINT8_MAX) {
135bf83f301SIdo Barnea    }
136bf83f301SIdo Barnea    virtual const void get_ip_str(char str[100]) const {
137bf83f301SIdo Barnea        snprintf(str, 4, "Bad");
138bf83f301SIdo Barnea    }
139bf83f301SIdo Barnea
140bf83f301SIdo Barnea protected:
141bf83f301SIdo Barnea    uint8_t    m_port;
142bf83f301SIdo Barnea    uint16_t   m_vlan;
143bf83f301SIdo Barnea    MacAddress m_mac;
144bf83f301SIdo Barnea};
145bf83f301SIdo Barnea
146bf83f301SIdo Barneaclass COneIPv4Info : public COneIPInfo {
147bf83f301SIdo Barnea    friend bool operator== (const COneIPv4Info& lhs, const COneIPv4Info& rhs);
148bf83f301SIdo Barnea
149bf83f301SIdo Barnea public:
150bf83f301SIdo Barnea    COneIPv4Info(uint32_t ip, uint16_t vlan, MacAddress mac) : COneIPInfo(vlan, mac) {
151bf83f301SIdo Barnea        m_ip = ip;
152bf83f301SIdo Barnea    }
153bf83f301SIdo Barnea    COneIPv4Info(uint32_t ip, uint16_t vlan) : COneIPv4Info (ip, vlan, MacAddress()) {
154bf83f301SIdo Barnea    }
155bf83f301SIdo Barnea    COneIPv4Info(uint32_t ip, uint16_t vlan, MacAddress mac, uint8_t port) : COneIPInfo(vlan, mac, port) {
156bf83f301SIdo Barnea        m_ip = ip;
157bf83f301SIdo Barnea    }
1583beb0705SIdo Barnea    ~COneIPv4Info() {};
1590c458152Simarom    uint32_t get_ip() const {return m_ip;}
160bf83f301SIdo Barnea    virtual uint8_t ip_ver() const {return IP4_VER;}
161bf83f301SIdo Barnea    virtual uint32_t get_arp_req_len() const {return 60;}
162bf83f301SIdo Barnea    virtual uint32_t get_grat_arp_len() const {return 60;}
163bf83f301SIdo Barnea    virtual void fill_arp_req_buf(uint8_t *p, uint16_t port_id, COneIPInfo *sip);
164bf83f301SIdo Barnea    virtual void fill_grat_arp_buf(uint8_t *p);
165bf83f301SIdo Barnea
166bf83f301SIdo Barnea private:
167bf83f301SIdo Barnea    virtual const void get_ip_str(char str[100]) const {
168bf83f301SIdo Barnea        ip_to_str(m_ip, str);
169bf83f301SIdo Barnea    };
170bf83f301SIdo Barnea    uint32_t m_ip;
171bf83f301SIdo Barnea};
172bf83f301SIdo Barnea
173bf83f301SIdo Barneainline bool operator== (const COneIPv4Info& lhs, const COneIPv4Info& rhs) {
174bf83f301SIdo Barnea    if (lhs.m_vlan != rhs.m_vlan)
175bf83f301SIdo Barnea        return false;
176bf83f301SIdo Barnea
177bf83f301SIdo Barnea    if (lhs.m_ip != rhs.m_ip)
178bf83f301SIdo Barnea        return false;
179bf83f301SIdo Barnea
180bf83f301SIdo Barnea    return true;
181bf83f301SIdo Barnea}
182bf83f301SIdo Barnea
183bf83f301SIdo Barneainline bool operator!= (const COneIPv4Info& lhs, const COneIPv4Info& rhs){ return !(lhs == rhs); }
184bf83f301SIdo Barnea
185bf83f301SIdo Barneaclass COneIPv6Info : public COneIPInfo {
186bf83f301SIdo Barnea    friend bool operator== (const COneIPv6Info& lhs, const COneIPv6Info& rhs);
187bf83f301SIdo Barnea
188bf83f301SIdo Barnea public:
189bf83f301SIdo Barnea    COneIPv6Info(uint16_t ip[8], uint16_t vlan, MacAddress mac) : COneIPInfo(vlan, mac) {
190bf83f301SIdo Barnea        memcpy(m_ip, ip, sizeof(m_ip));
191bf83f301SIdo Barnea    }
192bf83f301SIdo Barnea
193bf83f301SIdo Barnea    COneIPv6Info(uint16_t ip[8], uint16_t vlan) : COneIPv6Info(ip, vlan, MacAddress()){
194bf83f301SIdo Barnea    }
195bf83f301SIdo Barnea
196bf83f301SIdo Barnea    COneIPv6Info(uint16_t ip[8], uint16_t vlan, MacAddress mac, uint8_t port) : COneIPInfo(vlan, mac, port) {
197bf83f301SIdo Barnea        memcpy(m_ip, ip, sizeof(m_ip));
198bf83f301SIdo Barnea    }
1993beb0705SIdo Barnea    ~COneIPv6Info() {}
2004a2d56b6SIdo Barnea
201bf83f301SIdo Barnea    const uint8_t *get_ipv6() {return (uint8_t *)m_ip;}
202bf83f301SIdo Barnea    virtual uint8_t ip_ver() const {return IP6_VER;}
203bf83f301SIdo Barnea    virtual uint32_t get_arp_req_len() const {return 100; /* ??? put correct number for ipv6*/}
204bf83f301SIdo Barnea    virtual uint32_t get_grat_arp_len() const {return 100; /* ??? put correct number for ipv6*/}
205bf83f301SIdo Barnea    virtual void fill_arp_req_buf(uint8_t *p, uint16_t port_id, COneIPInfo *sip);
206bf83f301SIdo Barnea    virtual void fill_grat_arp_buf(uint8_t *p);
207bf83f301SIdo Barnea
208bf83f301SIdo Barnea private:
209bf83f301SIdo Barnea    virtual const void get_ip_str(char str[100]) {
210bf83f301SIdo Barnea        ipv6_to_str((ipaddr_t *)m_ip, str);
211bf83f301SIdo Barnea    }
212bf83f301SIdo Barnea    uint16_t m_ip[8];
213bf83f301SIdo Barnea};
214bf83f301SIdo Barnea
215bf83f301SIdo Barneainline bool operator== (const COneIPv6Info& lhs, const COneIPv6Info& rhs) {
216bf83f301SIdo Barnea    if (lhs.m_vlan != rhs.m_vlan)
217bf83f301SIdo Barnea        return false;
218bf83f301SIdo Barnea
219bf83f301SIdo Barnea    if (memcmp(&lhs.m_ip, &rhs.m_ip, sizeof(rhs.m_ip)))
220bf83f301SIdo Barnea        return false;
221bf83f301SIdo Barnea
222bf83f301SIdo Barnea    return true;
223bf83f301SIdo Barnea}
224bf83f301SIdo Barnea
225bf83f301SIdo Barneainline bool operator!= (const COneIPv6Info& lhs, const COneIPv6Info& rhs){ return !(lhs == rhs); }
226bf83f301SIdo Barnea
2274a2d56b6SIdo Barneatypedef std::map<CIpVlan, COneIPv4Info> ip_vlan_to_many_ip_t;
2280c458152Simaromtypedef std::map<CIpVlan, COneIPv4Info>::const_iterator ip_vlan_to_many_ip_iter_t;
2294a2d56b6SIdo Barneatypedef std::map<std::pair<uint16_t[8], uint16_t>, COneIPv6Info> ipv6_vlan_to_many_ipv6_t;
2304a2d56b6SIdo Barnea
231bf83f301SIdo Barneaclass CManyIPInfo {
232bf83f301SIdo Barnea public:
233bf83f301SIdo Barnea    CManyIPInfo () {
234bf83f301SIdo Barnea        m_iter_initiated = false;
235bf83f301SIdo Barnea    }
2360c458152Simarom    void insert(const COneIPv4Info &ip_info);
2370c458152Simarom    bool lookup(uint32_t ip, uint16_t vlan, MacAddress &ret_mac) const;
2380c458152Simarom    bool exists(uint32_t ip, uint16_t vlan = 0) const;
2390c458152Simarom    void clear();
241bf83f301SIdo Barnea    void dump(FILE *fd);
242bf83f301SIdo Barnea    uint32_t size() { return m_ipv4_resolve.size() + m_ipv6_resolve.size();}
243bf83f301SIdo Barnea    const COneIPInfo *get_first();
244bf83f301SIdo Barnea    const COneIPInfo *get_next();
2450c458152Simarom    const COneIPInfo *get_next_loop() {
2460c458152Simarom        const COneIPInfo *ip_info = get_next();
2470c458152Simarom        return (ip_info ? ip_info : get_next());
2480c458152Simarom    }
2500c458152Simarom    CManyIPInfo& operator = (const CManyIPInfo &rhs) {
2510c458152Simarom        m_ipv4_resolve = rhs.m_ipv4_resolve;
2520c458152Simarom        m_ipv6_resolve = rhs.m_ipv6_resolve;
2540c458152Simarom        m_iter_initiated = false;
2550c458152Simarom        return (*this);
2560c458152Simarom    }
258bf83f301SIdo Barnea private:
2590c458152Simarom    ip_vlan_to_many_ip_t      m_ipv4_resolve;
2600c458152Simarom    ipv6_vlan_to_many_ipv6_t  m_ipv6_resolve;
2624a2d56b6SIdo Barnea    ip_vlan_to_many_ip_iter_t m_ipv4_iter;
264bf83f301SIdo Barnea    bool m_iter_initiated;
2654a2d56b6SIdo Barnea
266bf83f301SIdo Barnea};
267bf83f301SIdo Barnea
269bf83f301SIdo Barnea#endif