summaryrefslogtreecommitdiffstats
path: root/lib/sockunion.h
blob: 146651225cdf7122810a5ab4fc45fc6324ea977a (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
142
143
144
145
146
147
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Socket union header.
 * Copyright (c) 1997 Kunihiro Ishiguro
 */

#ifndef _ZEBRA_SOCKUNION_H
#define _ZEBRA_SOCKUNION_H

#include "compiler.h"

#include "privs.h"
#include "if.h"
#include <sys/un.h>
#ifdef __OpenBSD__
#include <net/route.h>
#include <netmpls/mpls.h>
#endif

#ifdef __cplusplus
extern "C" {
#endif

union sockunion {
	struct sockaddr sa;
	struct sockaddr_in sin;
	struct sockaddr_in6 sin6;
	struct sockaddr_un sun;
#ifdef __OpenBSD__
	struct sockaddr_mpls smpls;
	struct sockaddr_rtlabel rtlabel;
#endif

	/* sockaddr_storage is guaranteed to be larger than the others */
	struct sockaddr_storage sa_storage;
};

/* clang-format off */
/* for functions that want to accept any sockaddr pointer without casts */
union sockaddrptr {
	uniontype(sockaddrptr, union sockunion, su)
	uniontype(sockaddrptr, struct sockaddr, sa)
	uniontype(sockaddrptr, struct sockaddr_in, sin)
	uniontype(sockaddrptr, struct sockaddr_in6, sin6)
	uniontype(sockaddrptr, struct sockaddr_un, sun)
#ifdef __OpenBSD__
	uniontype(sockaddrptr, struct sockaddr_mpls, smpls)
	uniontype(sockaddrptr, struct sockaddr_rtlabel, rtlabel)
#endif
	uniontype(sockaddrptr, struct sockaddr_storage, sa_storage)
} TRANSPARENT_UNION;

union sockaddrconstptr {
	uniontype(sockaddrconstptr, const union sockunion, su)
	uniontype(sockaddrconstptr, const struct sockaddr, sa)
	uniontype(sockaddrconstptr, const struct sockaddr_in, sin)
	uniontype(sockaddrconstptr, const struct sockaddr_in6, sin6)
	uniontype(sockaddrconstptr, const struct sockaddr_un, sun)
#ifdef __OpenBSD__
	uniontype(sockaddrconstptr, const struct sockaddr_mpls, smpls)
	uniontype(sockaddrconstptr, const struct sockaddr_rtlabel, rtlabel)
#endif
	uniontype(sockaddrconstptr, const struct sockaddr_storage, sa_storage)
} TRANSPARENT_UNION;
/* clang-format on */

enum connect_result { connect_error, connect_success, connect_in_progress };

/* Default address family. */
#define AF_INET_UNION AF_INET6

/* Sockunion address string length.  Same as INET6_ADDRSTRLEN. */
#define SU_ADDRSTRLEN 46

/* Macro to set link local index to the IPv6 address.  For KAME IPv6
   stack. */
#ifdef KAME
#define	IN6_LINKLOCAL_IFINDEX(a)  ((a).s6_addr[2] << 8 | (a).s6_addr[3])
#define SET_IN6_LINKLOCAL_IFINDEX(a, i)                                        \
	do {                                                                   \
		(a).s6_addr[2] = ((i) >> 8) & 0xff;                            \
		(a).s6_addr[3] = (i)&0xff;                                     \
	} while (0)
#else
#define	IN6_LINKLOCAL_IFINDEX(a)
#define SET_IN6_LINKLOCAL_IFINDEX(a, i)
#endif /* KAME */

#define sockunion_family(X)  (X)->sa.sa_family

#define sockunion2ip(X)      (X)->sin.sin_addr.s_addr

/* Prototypes. */
extern int str2sockunion(const char *, union sockunion *);
extern const char *sockunion2str(const union sockunion *, char *, size_t);
int in6addr_cmp(const struct in6_addr *addr1, const struct in6_addr *addr2);
extern int sockunion_cmp(const union sockunion *, const union sockunion *);
extern int sockunion_same(const union sockunion *, const union sockunion *);
extern unsigned int sockunion_hash(const union sockunion *);

extern size_t family2addrsize(int family);
extern size_t sockunion_get_addrlen(const union sockunion *);
extern const uint8_t *sockunion_get_addr(const union sockunion *);
extern void sockunion_set(union sockunion *, int family, const uint8_t *addr,
			  size_t bytes);

extern union sockunion *sockunion_str2su(const char *str);
extern int sockunion_accept(int sock, union sockunion *);
extern int sockunion_sizeof(const union sockunion *su);
extern int sockunion_stream_socket(union sockunion *);
extern int sockopt_reuseaddr(int);
extern int sockopt_reuseport(int);
extern int sockopt_v6only(int family, int sock);
extern int sockunion_bind(int sock, union sockunion *, unsigned short,
			  union sockunion *);
extern int sockopt_ttl(int family, int sock, int ttl);
extern int sockopt_minttl(int family, int sock, int minttl);
extern int sockunion_socket(const union sockunion *su);
extern const char *inet_sutop(const union sockunion *su, char *str);
extern enum connect_result sockunion_connect(int fd, const union sockunion *su,
					     unsigned short port, ifindex_t);
extern union sockunion *sockunion_getsockname(int);
extern union sockunion *sockunion_getpeername(int);
extern union sockunion *sockunion_dup(const union sockunion *);
extern void sockunion_free(union sockunion *);
extern void sockunion_init(union sockunion *);
extern int sockunion_is_null(const union sockunion *su);

#ifdef _FRR_ATTRIBUTE_PRINTFRR
#pragma FRR printfrr_ext "%pSU"  (union sockunion *)
#pragma FRR printfrr_ext "%pSU"  (struct sockaddr *)
#pragma FRR printfrr_ext "%pSU"  (struct sockaddr_storage *)
#pragma FRR printfrr_ext "%pSU"  (struct sockaddr_in *)
#pragma FRR printfrr_ext "%pSU"  (struct sockaddr_in6 *)
#pragma FRR printfrr_ext "%pSU"  (struct sockaddr_un *)

/* AF_INET/PF_INET & co., using "PF" to avoid confusion with AFI/SAFI */
#pragma FRR printfrr_ext "%dPF"  (int)
/* SOCK_STREAM & co. */
#pragma FRR printfrr_ext "%dSO"  (int)
#endif

#ifdef __cplusplus
}
#endif

#endif /* _ZEBRA_SOCKUNION_H */