summaryrefslogtreecommitdiffstats
path: root/src/if.h
blob: f58b3028fec05d8455bdaee03c93ba996a3892c3 (plain) (blame)
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/* SPDX-License-Identifier: BSD-2-Clause */
/*
 * dhcpcd - DHCP client daemon
 * Copyright (c) 2006-2020 Roy Marples <roy@marples.name>
 * All rights reserved

 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef INTERFACE_H
#define INTERFACE_H

#include <net/if.h>
#include <net/route.h>		/* for RTM_ADD et all */
#include <netinet/in.h>
#ifdef BSD
#include <netinet/in_var.h>	/* for IN_IFF_TENTATIVE et all */
#endif

#include <ifaddrs.h>

/* Some systems have in-built IPv4 DAD.
 * However, we need them to do DAD at carrier up as well. */
#ifdef IN_IFF_TENTATIVE
#  ifdef __NetBSD__
#    define NOCARRIER_PRESERVE_IP
#  endif
#endif

/*
 * Systems which handle 1 address per alias.
 * Currenly this is just Solaris.
 * While Linux can do aliased addresses, it is only useful for their
 * legacy ifconfig(8) tool which cannot display >1 IPv4 address
 * (it can display many IPv6 addresses which makes the limitation odd).
 * Linux has ip(8) which is a more feature rich tool, without the above
 * restriction.
 */
#ifndef ALIAS_ADDR
#  ifdef __sun
#    define ALIAS_ADDR
#  endif
#endif

#include "config.h"

/* POSIX defines ioctl request as an int, which Solaris and musl use.
 * Everyone else use an unsigned long, which happens to be the bigger one
 * so we use that in our on wire API. */
#ifdef IOCTL_REQUEST_TYPE
typedef IOCTL_REQUEST_TYPE	ioctl_request_t;
#else
typedef unsigned long		ioctl_request_t;
#endif

#include "dhcpcd.h"
#include "ipv4.h"
#include "ipv6.h"
#include "route.h"

#define EUI64_ADDR_LEN			8
#define INFINIBAND_ADDR_LEN		20

/* Linux 2.4 doesn't define this */
#ifndef ARPHRD_IEEE1394
#  define ARPHRD_IEEE1394		24
#endif

/* The BSD's don't define this yet */
#ifndef ARPHRD_INFINIBAND
#  define ARPHRD_INFINIBAND		32
#endif

/* Maximum frame length.
 * Support jumbo frames and some extra. */
#define	FRAMEHDRLEN_MAX			14	/* only ethernet support */
#define	FRAMELEN_MAX			(FRAMEHDRLEN_MAX + 9216)

/* Work out if we have a private address or not
 * 10/8
 * 172.16/12
 * 192.168/16
 */
#ifndef IN_PRIVATE
# define IN_PRIVATE(addr) (((addr & IN_CLASSA_NET) == 0x0a000000) ||	      \
	    ((addr & 0xfff00000)    == 0xac100000) ||			      \
	    ((addr & IN_CLASSB_NET) == 0xc0a80000))
#endif

#ifndef CLLADDR
#ifdef AF_LINK
#  define CLLADDR(sdl) (const void *)((sdl)->sdl_data + (sdl)->sdl_nlen)
#endif
#endif

#ifdef __sun
/* Solaris stupidly defines this for compat with BSD
 * but then ignores it. */
#undef RTF_CLONING

/* Solaris getifaddrs is very un-suitable for dhcpcd.
 * See if-sun.c for details why. */
struct ifaddrs;
int if_getifaddrs(struct ifaddrs **);
#define	getifaddrs	if_getifaddrs
int if_getsubnet(struct dhcpcd_ctx *, const char *, int, void *, size_t);
#endif

int if_ioctl(struct dhcpcd_ctx *, ioctl_request_t, void *, size_t);
#ifdef HAVE_PLEDGE
#define	pioctl(ctx, req, data, len) if_ioctl((ctx), (req), (data), (len))
#else
#define	pioctl(ctx, req, data, len) ioctl((ctx)->pf_inet_fd, (req),(data),(len))
#endif
int if_getflags(struct interface *);
int if_setflag(struct interface *, short, short);
#define if_up(ifp) if_setflag((ifp), (IFF_UP | IFF_RUNNING), 0)
#define if_down(ifp) if_setflag((ifp), 0, IFF_UP);
bool if_valid_hwaddr(const uint8_t *, size_t);
struct if_head *if_discover(struct dhcpcd_ctx *, struct ifaddrs **,
    int, char * const *);
void if_markaddrsstale(struct if_head *);
void if_learnaddrs(struct dhcpcd_ctx *, struct if_head *, struct ifaddrs **);
void if_deletestaleaddrs(struct if_head *);
struct interface *if_find(struct if_head *, const char *);
struct interface *if_findindex(struct if_head *, unsigned int);
struct interface *if_loopback(struct dhcpcd_ctx *);
void if_free(struct interface *);
int if_domtu(const struct interface *, short int);
#define if_getmtu(ifp) if_domtu((ifp), 0)
#define if_setmtu(ifp, mtu) if_domtu((ifp), (mtu))
int if_carrier(struct interface *);

#ifdef ALIAS_ADDR
int if_makealias(char *, size_t, const char *, int);
#endif

int if_mtu_os(const struct interface *);

/*
 * Helper to decode an interface name of bge0:1 to
 * devname = bge0, drvname = bge0, ppa = 0, lun = 1.
 * If ppa or lun are invalid they are set to -1.
 */
struct if_spec {
	char ifname[IF_NAMESIZE];
	char devname[IF_NAMESIZE];
	char drvname[IF_NAMESIZE];
	int ppa;
	int vlid;
	int lun;
};
int if_nametospec(const char *, struct if_spec *);

/* The below functions are provided by if-KERNEL.c */
int if_conf(struct interface *);
int if_init(struct interface *);
int if_getssid(struct interface *);
bool if_ignore(struct dhcpcd_ctx *, const char *);
int if_vimaster(struct dhcpcd_ctx *ctx, const char *);
unsigned short if_vlanid(const struct interface *);
int if_opensockets(struct dhcpcd_ctx *);
int if_opensockets_os(struct dhcpcd_ctx *);
void if_closesockets(struct dhcpcd_ctx *);
void if_closesockets_os(struct dhcpcd_ctx *);
int if_handlelink(struct dhcpcd_ctx *);
int if_randomisemac(struct interface *);
int if_setmac(struct interface *ifp, void *, uint8_t);

/* dhcpcd uses the same routing flags as BSD.
 * If the platform doesn't use these flags,
 * map them in the platform interace file. */
#ifndef RTM_ADD
#define RTM_ADD		0x1	/* Add Route */
#define RTM_DELETE	0x2	/* Delete Route */
#define RTM_CHANGE	0x3	/* Change Metrics or flags */
#define RTM_GET		0x4	/* Report Metrics */
#endif

/* Define SOCK_CLOEXEC and SOCK_NONBLOCK for systems that lack it.
 * xsocket() in if.c will map them to fctnl FD_CLOEXEC and O_NONBLOCK. */
#ifdef SOCK_CLOEXEC
# define HAVE_SOCK_CLOEXEC
#else
# define SOCK_CLOEXEC	0x10000000
#endif
#ifdef SOCK_NONBLOCK
# define HAVE_SOCK_NONBLOCK
#else
# define SOCK_NONBLOCK	0x20000000
#endif

int if_route(unsigned char, const struct rt *rt);
int if_initrt(struct dhcpcd_ctx *, rb_tree_t *, int);

int if_missfilter(struct interface *, struct sockaddr *);
int if_missfilter_apply(struct dhcpcd_ctx *);

#ifdef INET
int if_address(unsigned char, const struct ipv4_addr *);
int if_addrflags(const struct interface *, const struct in_addr *,
    const char *);

#endif

#ifdef INET6
void if_disable_rtadv(void);
void if_setup_inet6(const struct interface *);
int ip6_forwarding(const char *ifname);

struct ra;
struct ipv6_addr;

int if_applyra(const struct ra *);
int if_address6(unsigned char, const struct ipv6_addr *);
int if_addrflags6(const struct interface *, const struct in6_addr *,
    const char *);
int if_getlifetime6(struct ipv6_addr *);

#else
#define if_checkipv6(a, b, c) (-1)
#endif

int if_machinearch(char *, size_t);
struct interface *if_findifpfromcmsg(struct dhcpcd_ctx *,
    struct msghdr *, int *);
int xsocket(int, int, int);

#ifdef __linux__
int if_linksocket(struct sockaddr_nl *, int);
int if_getnetlink(struct dhcpcd_ctx *, struct iovec *, int, int,
    int (*)(struct dhcpcd_ctx *, void *, struct nlmsghdr *), void *);
#endif
#endif