aboutsummaryrefslogtreecommitdiffstats
path: root/hicn-light/src/hicn/core/address.h
blob: 38cd1e87c70b58897adfd0d0ddb0bf90bfdcff63 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
 * Copyright (c) 2021 Cisco and/or its affiliates.
 * 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.
 */

/**
 * \file address.h
 * \brief Address
 */

#ifndef HICNLIGHT_ADDRESS_H
#define HICNLIGHT_ADDRESS_H

#include <netinet/in.h>

#include <string.h>  // memcmp
#include <hicn/util/ip_address.h>
#include <netinet/in.h>

typedef union {
  struct sockaddr_in as_sin;
  struct sockaddr_in6 as_sin6;
  struct sockaddr as_sa;
  struct sockaddr_storage as_ss;
} address_t;

#define address_equals(a, b) (memcmp(a, b, sizeof(address_t)) == 0)

#define address_family(address) ((address)->as_ss.ss_family)

#define address4(address) ((struct sockaddr_in *)(address))
#define address6(address) ((struct sockaddr_in6 *)(address))
#define address_sa(address) ((struct sockaddr *)(address))

#define address4_ip(address) (address4(address)->sin_addr)
#define address6_ip(address) (address6(address)->sin6_addr)
#define address6_scope_id(address) (address4_ptr(address)->sin6_scope_id)

#define address_socklen(address)                                        \
  (((address)->as_ss.ss_family == AF_INET) ? sizeof(struct sockaddr_in) \
                                           : sizeof(struct sockaddr_in6))

#define address4_is_local(address) \
  ((htonl((address4_ip(address)).s_addr) & 0xFF000000) == 0x7F000000)

static inline bool _address6_is_local(struct sockaddr_in6 *sin6) {
  return IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr);
}

#define address6_is_local(address) (_address6_is_local(address6(address)))

#define address_is_local(address)                                      \
  ((address)->as_ss.ss_family == AF_INET) ? address4_is_local(address) \
                                          : address6_is_local(address)

int address_from_ip_port(address_t *address, int family,
                         hicn_ip_address_t *addr, uint16_t port);

static inline address_t ADDRESS4(in_addr_t in_addr, int port) {
  address_t address = {
      .as_sin =
          {
              .sin_family = AF_INET,
              .sin_port = htons(port),
              .sin_addr = {.s_addr = htonl(in_addr)},
          },
  };

  return address;
}

#define ADDRESS4_LOCALHOST(port) ADDRESS4(INADDR_LOOPBACK, (port))

/**
 * @brief Helper function to avoid macro expansion in c++ tests. Wrapper around
 * 'ADDRESS4_LOCALHOST()'.
 *
 * @param port
 * @return address_t
 */
address_t _ADDRESS4_LOCALHOST(uint16_t port);

#define ADDRESS4_ANY(port) ADDRESS4(INADDR_ANY, (port))

static inline address_t ADDRESS6(struct in6_addr in_addr, int port) {
  address_t address = {
      .as_sin6 =
          {
              .sin6_family = AF_INET6,
              .sin6_port = htons(port),
              .sin6_addr = in_addr,
          },
  };

  return address;
}

#define ADDRESS6_LOCALHOST(port) ADDRESS6(in6addr_loopback, (port))
#define ADDRESS6_ANY(port) ADDRESS6((struct in6_addr)IN6ADDR_ANY_INIT, port)

#define ADDRESS_ANY(family, port) \
  ((family == AF_INET) ? ADDRESS4_ANY(port) : ADDRESS6_ANY(port))

extern const char *_address_family_str[];

#define address_family_str(address) \
  (_address_family_str[address_family(address)])

#define address4_empty(address) (address4_ip(address).s_addr == 0)
#define address6_empty(address)                       \
  (memcmp(address6_ip(address).s6_addr, &in6addr_any, \
          sizeof(struct in6_addr)) == 0)
#define address_empty(address)                                  \
  (address_family(address) == AF_INET ? address4_empty(address) \
                                      : address6_empty(address))

/**
 * @brief Return the string representation and the port of the IP address
 * provided.
 *
 * @param[in] address Address to obtain the string representation from.
 * @param[in, out] buffer String to store the string representation of the
 * address. It contains "N/A" in case of failure (see return value).
 * @param[in, out] port Integer to store the the port. It contains -1 in case of
 * failure (see return value). If NULL, it will not be used to store the port.
 * @return int 0 if success, failure otherwise.
 */

int address_to_string(const address_t *address, char *buffer, int *port);

#endif /* HICNLIGHT_ADDRESS_H */