1#ifndef UTL_IP_H
2#define UTL_IP_H
3/*
4 Cisco Systems, Inc.
5*/
6
7/*
8Copyright (c) 2016-2016 Cisco Systems, Inc.
9
10Licensed under the Apache License, Version 2.0 (the "License");
11you may not use this file except in compliance with the License.
12You may obtain a copy of the License at
13
14    http://www.apache.org/licenses/LICENSE-2.0
15
16Unless required by applicable law or agreed to in writing, software
17distributed under the License is distributed on an "AS IS" BASIS,
18WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19See the License for the specific language governing permissions and
20limitations under the License.
21*/
22#include <map>
23#include <sys/socket.h>
24#include <netinet/in.h>
25#include <arpa/inet.h>
26#include "common/basic_utils.h"
27#include "common/Network/Packet/CPktCmn.h"
28#include "common/Network/Packet/MacAddress.h"
29
30/* IP address, last 32-bits of IPv6 remaps IPv4 */
31typedef struct {
32    uint16_t v6[6];  /* First 96-bits of IPv6 */
33    uint32_t v4;  /* Last 32-bits IPv6 overloads v4 */
34} ipaddr_t;
35
36// Routine to create IPv4 address string
37inline int ip_to_str(uint32_t ip,char * str) {
38    uint32_t ipv4 = PKT_HTONL(ip);
39    inet_ntop(AF_INET, (const char *)&ipv4, str, INET_ADDRSTRLEN);
40    return(strlen(str));
41}
42
43inline std::string ip_to_str(uint32_t ip) {
44    char tmp[INET_ADDRSTRLEN];
45    ip_to_str(ip, tmp);
46    return tmp;
47}
48
49// Routine to create IPv6 address string
50inline int ipv6_to_str(ipaddr_t *ip, char * str) {
51    int idx=0;
52    uint16_t ipv6[8];
53    for (uint8_t i=0; i<6; i++) {
54        ipv6[i] = PKT_HTONS(ip->v6[i]);
55    }
56    uint32_t ipv4 = PKT_HTONL(ip->v4);
57    ipv6[6] = ipv4 & 0xffff;
58    ipv6[7] = ipv4 >> 16;
59
60    str[idx++] = '[';
61    inet_ntop(AF_INET6, (const char *)&ipv6, &str[1], INET6_ADDRSTRLEN);
62    idx = strlen(str);
63    str[idx++] = ']';
64    str[idx] = 0;
65    return(idx);
66}
67
68inline std::string ip_to_str(uint8_t *ip) {
69    char tmp[INET6_ADDRSTRLEN];
70    ipv6_to_str((ipaddr_t *)ip, tmp);
71    return tmp;
72}
73
74class CIpVlan {
75    // to be able to use this in map
76    friend bool operator<(const CIpVlan& l, const CIpVlan& r) {
77        if (l.get_ip() == r.get_ip()) {
78            return l.get_vlan() < r.get_vlan();
79        } else {
80            return l.get_ip() < r.get_ip();
81        }
82    }
83
84 public:
85    CIpVlan(uint32_t ip, uint16_t vlan) {
86        m_ip = ip;
87        m_vlan = vlan;
88    }
89    uint16_t get_vlan() const {return m_vlan;}
90    void set_vlan(uint16_t vlan) {m_vlan = vlan;}
91    uint16_t get_ip() const {return m_ip;}
92    void set_ip(uint32_t ip) {m_ip = ip;}
93
94 private:
95    uint32_t m_ip;
96    uint16_t m_vlan;
97};
98
99
100class COneIPInfo {
101 public:
102    enum {
103        IP4_VER=4,
104        IP6_VER=6,
105    } COneIPInfo_ip_types;
106
107 public:
108    virtual ~COneIPInfo() {}
109    virtual void get_mac(uint8_t *mac) const {
110        m_mac.copyToArray(mac);
111    }
112    virtual void set_mac(uint8_t *mac) {
113        m_mac.set(mac);
114    }
115    uint16_t get_vlan() const {return m_vlan;}
116    uint16_t get_port() const {return m_port;}
117    void set_port(uint8_t port) {m_port = port;}
118    virtual void dump(FILE *fd) const {
119        dump(fd, "");
120    }
121    virtual void dump(FILE *fd, const char *offset) const;
122    virtual uint8_t ip_ver() const {return 0;}
123    virtual uint32_t get_arp_req_len() const=0;
124    virtual uint32_t get_grat_arp_len() const=0;
125    virtual void fill_arp_req_buf(uint8_t *p, uint16_t port_id, COneIPInfo *sip)=0;
126    virtual void fill_grat_arp_buf(uint8_t *p)=0;
127    virtual bool resolve_needed() const;
128
129 protected:
130    COneIPInfo(uint16_t vlan, MacAddress mac, uint8_t port) : m_mac(mac) {
131        m_vlan = vlan;
132        m_port = port;
133    }
134    COneIPInfo(uint16_t vlan, MacAddress mac) : COneIPInfo(vlan, mac, UINT8_MAX) {
135    }
136    virtual const void get_ip_str(char str[100]) const {
137        snprintf(str, 4, "Bad");
138    }
139
140 protected:
141    uint8_t    m_port;
142    uint16_t   m_vlan;
143    MacAddress m_mac;
144};
145
146class COneIPv4Info : public COneIPInfo {
147    friend bool operator== (const COneIPv4Info& lhs, const COneIPv4Info& rhs);
148
149 public:
150    COneIPv4Info(uint32_t ip, uint16_t vlan, MacAddress mac) : COneIPInfo(vlan, mac) {
151        m_ip = ip;
152    }
153    COneIPv4Info(uint32_t ip, uint16_t vlan) : COneIPv4Info (ip, vlan, MacAddress()) {
154    }
155    COneIPv4Info(uint32_t ip, uint16_t vlan, MacAddress mac, uint8_t port) : COneIPInfo(vlan, mac, port) {
156        m_ip = ip;
157    }
158    ~COneIPv4Info() {};
159    uint32_t get_ip() const {return m_ip;}
160    virtual uint8_t ip_ver() const {return IP4_VER;}
161    virtual uint32_t get_arp_req_len() const {return 60;}
162    virtual uint32_t get_grat_arp_len() const {return 60;}
163    virtual void fill_arp_req_buf(uint8_t *p, uint16_t port_id, COneIPInfo *sip);
164    virtual void fill_grat_arp_buf(uint8_t *p);
165
166 private:
167    virtual const void get_ip_str(char str[100]) const {
168        ip_to_str(m_ip, str);
169    };
170    uint32_t m_ip;
171};
172
173inline bool operator== (const COneIPv4Info& lhs, const COneIPv4Info& rhs) {
174    if (lhs.m_vlan != rhs.m_vlan)
175        return false;
176
177    if (lhs.m_ip != rhs.m_ip)
178        return false;
179
180    return true;
181}
182
183inline bool operator!= (const COneIPv4Info& lhs, const COneIPv4Info& rhs){ return !(lhs == rhs); }
184
185class COneIPv6Info : public COneIPInfo {
186    friend bool operator== (const COneIPv6Info& lhs, const COneIPv6Info& rhs);
187
188 public:
189    COneIPv6Info(uint16_t ip[8], uint16_t vlan, MacAddress mac) : COneIPInfo(vlan, mac) {
190        memcpy(m_ip, ip, sizeof(m_ip));
191    }
192
193    COneIPv6Info(uint16_t ip[8], uint16_t vlan) : COneIPv6Info(ip, vlan, MacAddress()){
194    }
195
196    COneIPv6Info(uint16_t ip[8], uint16_t vlan, MacAddress mac, uint8_t port) : COneIPInfo(vlan, mac, port) {
197        memcpy(m_ip, ip, sizeof(m_ip));
198    }
199    ~COneIPv6Info() {}
200
201    const uint8_t *get_ipv6() {return (uint8_t *)m_ip;}
202    virtual uint8_t ip_ver() const {return IP6_VER;}
203    virtual uint32_t get_arp_req_len() const {return 100; /* ??? put correct number for ipv6*/}
204    virtual uint32_t get_grat_arp_len() const {return 100; /* ??? put correct number for ipv6*/}
205    virtual void fill_arp_req_buf(uint8_t *p, uint16_t port_id, COneIPInfo *sip);
206    virtual void fill_grat_arp_buf(uint8_t *p);
207
208 private:
209    virtual const void get_ip_str(char str[100]) {
210        ipv6_to_str((ipaddr_t *)m_ip, str);
211    }
212    uint16_t m_ip[8];
213};
214
215inline bool operator== (const COneIPv6Info& lhs, const COneIPv6Info& rhs) {
216    if (lhs.m_vlan != rhs.m_vlan)
217        return false;
218
219    if (memcmp(&lhs.m_ip, &rhs.m_ip, sizeof(rhs.m_ip)))
220        return false;
221
222    return true;
223}
224
225inline bool operator!= (const COneIPv6Info& lhs, const COneIPv6Info& rhs){ return !(lhs == rhs); }
226
227typedef std::map<CIpVlan, COneIPv4Info> ip_vlan_to_many_ip_t;
228typedef std::map<CIpVlan, COneIPv4Info>::const_iterator ip_vlan_to_many_ip_iter_t;
229typedef std::map<std::pair<uint16_t[8], uint16_t>, COneIPv6Info> ipv6_vlan_to_many_ipv6_t;
230
231class CManyIPInfo {
232 public:
233    CManyIPInfo () {
234        m_iter_initiated = false;
235    }
236    void insert(const COneIPv4Info &ip_info);
237    bool lookup(uint32_t ip, uint16_t vlan, MacAddress &ret_mac) const;
238    bool exists(uint32_t ip, uint16_t vlan = 0) const;
239    void clear();
240
241    void dump(FILE *fd);
242    uint32_t size() { return m_ipv4_resolve.size() + m_ipv6_resolve.size();}
243    const COneIPInfo *get_first();
244    const COneIPInfo *get_next();
245    const COneIPInfo *get_next_loop() {
246        const COneIPInfo *ip_info = get_next();
247        return (ip_info ? ip_info : get_next());
248    }
249
250    CManyIPInfo& operator = (const CManyIPInfo &rhs) {
251        m_ipv4_resolve = rhs.m_ipv4_resolve;
252        m_ipv6_resolve = rhs.m_ipv6_resolve;
253
254        m_iter_initiated = false;
255        return (*this);
256    }
257
258 private:
259    ip_vlan_to_many_ip_t      m_ipv4_resolve;
260    ipv6_vlan_to_many_ipv6_t  m_ipv6_resolve;
261
262    ip_vlan_to_many_ip_iter_t m_ipv4_iter;
263
264    bool m_iter_initiated;
265
266};
267
268
269#endif
270