summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/inet/arp_impl.h
blob: a9be780a42b710581310268e1d418a8d4b609377 (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
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
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_ARP_IMPL_H
#define	_ARP_IMPL_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#ifdef	__cplusplus
extern "C" {
#endif

#ifdef _KERNEL

#include <sys/types.h>
#include <sys/stream.h>
#include <net/if.h>
#include <sys/netstack.h>

/* ARP kernel hash size; used for mdb support */
#define	ARP_HASH_SIZE	256

/* Named Dispatch Parameter Management Structure */
typedef struct arpparam_s {
	uint32_t	arp_param_min;
	uint32_t	arp_param_max;
	uint32_t	arp_param_value;
	char		*arp_param_name;
} arpparam_t;

/* ARL Structure, one per link level device */
typedef struct arl_s {
	struct arl_s	*arl_next;		/* ARL chain at arl_g_head */
	queue_t		*arl_rq;		/* Read queue pointer */
	queue_t		*arl_wq;		/* Write queue pointer */
	t_uscalar_t	arl_ppa;		/* DL_ATTACH parameter */
	char		arl_name[LIFNAMSIZ];	/* Lower level name */
	mblk_t		*arl_unbind_mp;
	mblk_t		*arl_detach_mp;
	t_uscalar_t	arl_provider_style;	/* From DL_INFO_ACK */
	mblk_t		*arl_queue;		/* Queued commands head */
	mblk_t		*arl_queue_tail;	/* Queued commands tail */
	uint32_t	arl_flags;		/* ARL_F_* values below */
	t_uscalar_t	arl_dlpi_pending;	/* pending DLPI request */
	mblk_t		*arl_dlpi_deferred;	/* Deferred DLPI messages */
	uint_t		arl_state;		/* lower interface state */
	uint_t		arl_closing : 1;	/* stream is closing */
	uint32_t	arl_index;		/* instance number */
	struct arlphy_s	*arl_phy;		/* physical info, if any */
} arl_t;

/*
 * There is no field to get from an arl_t to an arp_stack_t, but this
 * macro does it.
 */
#define	ARL_TO_ARPSTACK(_arl)	(((ar_t *)(_arl)->arl_rq->q_ptr)->ar_as)

/* ARL physical info structure for a link level device */
typedef struct arlphy_s {
	uint32_t	ap_arp_hw_type;		/* hardware type */
	uchar_t		*ap_arp_addr;		/* multicast address to use */
	uchar_t		*ap_hw_addr;		/* hardware address */
	uint32_t	ap_hw_addrlen;		/* hardware address length */
	mblk_t		*ap_xmit_mp;		/* DL_UNITDATA_REQ template */
	t_uscalar_t	ap_xmit_addroff;	/* address offset in xmit_mp */
	t_uscalar_t	ap_xmit_sapoff;		/* sap offset in xmit_mp */
	t_scalar_t	ap_saplen;		/* sap length */
	clock_t		ap_defend_start;	/* start of 1-hour period */
	uint_t		ap_defend_count;	/* # of unbidden broadcasts */
	uint_t		ap_notifies : 1,	/* handles DL_NOTE_LINK */
			ap_link_down : 1;	/* DL_NOTE status */
} arlphy_t;

/* ARP Cache Entry */
typedef struct ace_s {
	struct ace_s	*ace_next;	/* Hash chain next pointer */
	struct ace_s	**ace_ptpn;	/* Pointer to previous next */
	struct arl_s	*ace_arl;	/* Associated arl */
	uint32_t	ace_proto;	/* Protocol for this ace */
	uint32_t	ace_flags;
	uchar_t		*ace_proto_addr;
	uint32_t	ace_proto_addr_length;
	uchar_t		*ace_proto_mask; /* Mask for matching addr */
	uchar_t		*ace_proto_extract_mask; /* For mappings */
	uchar_t		*ace_hw_addr;
	uint32_t	ace_hw_addr_length;
	uint32_t	ace_hw_extract_start;	/* For mappings */
	mblk_t		*ace_mp;		/* mblk we are in */
	mblk_t		*ace_query_mp;		/* outstanding query chain */
	clock_t		ace_last_bcast;		/* last broadcast Response */
	clock_t		ace_xmit_interval;
	int		ace_xmit_count;
} ace_t;

#define	ARPHOOK_INTERESTED_PHYSICAL_IN(as)	\
	(as->as_arp_physical_in_event.he_interested)
#define	ARPHOOK_INTERESTED_PHYSICAL_OUT(as)	\
	(as->as_arp_physical_out_event.he_interested)

#define	ARP_HOOK_IN(_hook, _event, _ilp, _hdr, _fm, _m, as)	\
								\
	if ((_hook).he_interested) {                       	\
		hook_pkt_event_t info;                          \
								\
		info.hpe_ifp = _ilp;                       	\
		info.hpe_ofp = 0;                       	\
		info.hpe_hdr = _hdr;                            \
		info.hpe_mp = &(_fm);                           \
		info.hpe_mb = _m;                               \
		if (hook_run(_event, (hook_data_t)&info, 	\
		    as->as_netstack) != 0) {			\
			if (_fm != NULL) {                      \
				freemsg(_fm);                   \
				_fm = NULL;                     \
			}                                       \
			_hdr = NULL;                            \
			_m = NULL;                              \
		} else {                                        \
			_hdr = info.hpe_hdr;                    \
			_m = info.hpe_mb;                       \
		}                                               \
	}

#define	ARP_HOOK_OUT(_hook, _event, _olp, _hdr, _fm, _m, as)	\
								\
	if ((_hook).he_interested) {                       	\
		hook_pkt_event_t info;                          \
								\
		info.hpe_ifp = 0;                       	\
		info.hpe_ofp = _olp;                       	\
		info.hpe_hdr = _hdr;                            \
		info.hpe_mp = &(_fm);                           \
		info.hpe_mb = _m;                               \
		if (hook_run(_event, (hook_data_t)&info,	\
		    as->as_netstack) != 0) {			\
			if (_fm != NULL) {                      \
				freemsg(_fm);                   \
				_fm = NULL;                     \
			}                                       \
			_hdr = NULL;                            \
			_m = NULL;                              \
		} else {                                        \
			_hdr = info.hpe_hdr;                    \
			_m = info.hpe_mb;                       \
		}                                               \
	}

#define	ACE_EXTERNAL_FLAGS_MASK \
	(ACE_F_PERMANENT | ACE_F_PUBLISH | ACE_F_MAPPING | ACE_F_MYADDR | \
	ACE_F_AUTHORITY)

/*
 * ARP stack instances
 */
struct arp_stack {
	netstack_t	*as_netstack;	/* Common netstack */
	void		*as_head;	/* AR Instance Data List Head */
	caddr_t		as_nd;		/* AR Named Dispatch Head */
	struct arl_s	*as_arl_head;	/* ARL List Head */
	arpparam_t	*as_param_arr; 	/* ndd variable table */

	/* ARP Cache Entry Hash Table */
	ace_t	*as_ce_hash_tbl[ARP_HASH_SIZE];
	ace_t	*as_ce_mask_entries;

	/*
	 * With the introduction of netinfo (neti kernel module),
	 * it is now possible to access data structures in the ARP module
	 * without the code being executed in the context of the IP module,
	 * thus there is no locking being enforced through the use of STREAMS.
	 * as_arl_lock is used to protect as_arl_head list.
	 */
	krwlock_t	as_arl_lock;

	uint32_t	as_arp_index_counter;
	uint32_t	as_arp_counter_wrapped;

	/* arp_neti.c */
	hook_family_t	as_arproot;

	/*
	 * Hooks for ARP
	 */
	hook_event_t	as_arp_physical_in_event;
	hook_event_t	as_arp_physical_out_event;
	hook_event_t	as_arp_nic_events;

	hook_event_token_t	as_arp_physical_in;
	hook_event_token_t	as_arp_physical_out;
	hook_event_token_t	as_arpnicevents;

	net_data_t	as_net_data;
};
typedef struct arp_stack arp_stack_t;

#define	ARL_F_NOARP	0x01

#define	ARL_S_DOWN	0x00
#define	ARL_S_PENDING	0x01
#define	ARL_S_UP	0x02

/* AR Structure, one per upper stream */
typedef struct ar_s {
	queue_t		*ar_rq;	/* Read queue pointer */
	queue_t		*ar_wq;	/* Write queue pointer */
	arl_t		*ar_arl;	/* Associated arl */
	cred_t		*ar_credp;	/* Credentials associated w/ open */
	struct ar_s	*ar_arl_ip_assoc;	/* ARL - IP association */
	uint32_t
			ar_ip_acked_close : 1,	/* IP has acked the close */
			ar_on_ill_stream : 1;	/* Module below is IP */
	arp_stack_t	*ar_as;
} ar_t;

extern void	arp_hook_init(arp_stack_t *);
extern void	arp_hook_destroy(arp_stack_t *);
extern void	arp_net_init(arp_stack_t *, netstack_t *);
extern void	arp_net_destroy(arp_stack_t *);

#endif	/* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _ARP_IMPL_H */