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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
|
/* $OpenBSD: in_pcb.h,v 1.159 2024/11/05 10:49:23 bluhm Exp $ */
/* $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* 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.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
*/
/*
* Copyright (c) 1982, 1986, 1990, 1993
* The Regents of the University of California. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)in_pcb.h 8.1 (Berkeley) 6/10/93
*/
#ifndef _NETINET_IN_PCB_H_
#define _NETINET_IN_PCB_H_
#include <sys/queue.h>
#include <sys/mutex.h>
#include <sys/rwlock.h>
#include <sys/refcnt.h>
#include <netinet/ip6.h>
#include <netinet/icmp6.h>
#include <netinet/ip_ipsp.h>
#include <crypto/siphash.h>
/*
* Locks used to protect struct members in this file:
* I immutable after creation
* N net lock
* t inpt_mtx pcb table mutex
* y inpt_notify pcb table rwlock for notify
* L pf_inp_mtx link pf to inp mutex
* s so_lock socket rwlock
*/
/*
* The pcb table mutex guarantees that all inpcb are consistent and
* that bind(2) and connect(2) create unique combinations of
* laddr/faddr/lport/fport/rtalbleid. This mutex is used to protect
* both address consistency and inpcb lookup during protocol input.
* All writes to inp_[lf]addr take table mutex. A per socket lock is
* needed, so that socket layer input have a consistent view at these
* values.
*
* In soconnect() and sosend() a per pcb mutex cannot be used. They
* eventually call IP output which takes pf lock which is a sleeping lock.
* Also connect(2) does a route lookup for source selection. There
* route resolve happens, which creates a route, which sends a route
* message, which needs route lock, which is a rw-lock.
*
* On the other hand a mutex should be used in protocol input. It
* does not make sense to do a process switch per packet. Better spin
* until the packet can be processed.
*
* So there are three locks. Table mutex is for writing inp_[lf]addr/port
* and lookup, socket rw-lock to separate sockets in system calls, and
* socket buffer mutex to protect socket receive buffer. Changing
* inp_[lf]addr/port takes both per socket rw-lock and global table mutex.
* Protocol input only reads inp_[lf]addr/port during lookup and is safe.
*/
struct pf_state_key;
union inpaddru {
struct in_addr iau_addr;
struct in6_addr iau_addr6;
};
/*
* Common structure pcb for internet protocol implementation.
* Here are stored pointers to local and foreign host table
* entries, local and foreign socket numbers, and pointers
* up (to a socket structure) and down (to a protocol-specific)
* control block.
*/
struct inpcb {
LIST_ENTRY(inpcb) inp_hash; /* [t] local and foreign hash */
LIST_ENTRY(inpcb) inp_lhash; /* [t] local port hash */
TAILQ_ENTRY(inpcb) inp_queue; /* [t] inet PCB queue */
SIMPLEQ_ENTRY(inpcb) inp_notify; /* [y] notify or udp append */
struct inpcbtable *inp_table; /* [I] inet queue/hash table */
union inpaddru inp_faddru; /* [t] Foreign address. */
union inpaddru inp_laddru; /* [t] Local address. */
#define inp_faddr inp_faddru.iau_addr
#define inp_faddr6 inp_faddru.iau_addr6
#define inp_laddr inp_laddru.iau_addr
#define inp_laddr6 inp_laddru.iau_addr6
u_int16_t inp_fport; /* [t] foreign port */
u_int16_t inp_lport; /* [t] local port */
struct socket *inp_socket; /* [I] back pointer to socket */
caddr_t inp_ppcb; /* pointer to per-protocol pcb */
struct route inp_route; /* cached route */
struct refcnt inp_refcnt; /* refcount PCB, delay memory free */
int inp_flags; /* generic IP/datagram flags */
union { /* Header prototype. */
struct ip hu_ip;
struct ip6_hdr hu_ipv6;
} inp_hu;
#define inp_ip inp_hu.hu_ip
#define inp_ipv6 inp_hu.hu_ipv6
union {
struct mbuf *inp_options; /* IPv4 options */
struct ip6_pktopts *inp_outputopts6; /* IPv6 options */
};
int inp_hops;
union {
struct ip_moptions *mou_mo;
struct ip6_moptions *mou_mo6;
} inp_mou;
#define inp_moptions inp_mou.mou_mo /* [N] IPv4 multicast options */
#define inp_moptions6 inp_mou.mou_mo6 /* [N] IPv6 multicast options */
struct ipsec_level inp_seclevel; /* [N] IPsec level of socket */
u_char inp_ip_minttl; /* minimum TTL or drop */
#define inp_ip6_minhlim inp_ip_minttl /* minimum Hop Limit or drop */
#define inp_flowinfo inp_hu.hu_ipv6.ip6_flow
int inp_cksum6;
struct icmp6_filter *inp_icmp6filt;
struct pf_state_key *inp_pf_sk; /* [L] */
struct mbuf *(*inp_upcall)(void *, struct mbuf *,
struct ip *, struct ip6_hdr *, void *, int);
void *inp_upcall_arg;
u_int inp_rtableid; /* [t] */
int inp_pipex; /* pipex indication */
uint16_t inp_flowid; /* [s] */
};
LIST_HEAD(inpcbhead, inpcb);
struct inpcb_iterator {
LIST_ENTRY(inpcb) inp_hash; /* unused */
LIST_ENTRY(inpcb) inp_lhash; /* unused */
TAILQ_ENTRY(inpcb) inp_queue; /* [t] inet PCB queue */
SIMPLEQ_ENTRY(inpcb) inp_notify; /* unused */
struct inpcbtable *inp_table; /* [I] always NULL */
};
static inline int
in_pcb_is_iterator(struct inpcb *inp)
{
return (inp->inp_table == NULL ? 1 : 0);
}
struct inpcbtable {
struct mutex inpt_mtx; /* protect queue and hash */
struct rwlock inpt_notify; /* protect inp_notify list */
TAILQ_HEAD(inpthead, inpcb) inpt_queue; /* [t] inet PCB queue */
struct inpcbhead *inpt_hashtbl; /* [t] local and foreign hash */
struct inpcbhead *inpt_lhashtbl; /* [t] local port hash */
SIPHASH_KEY inpt_key, inpt_lkey; /* [I] secrets for hashes */
u_long inpt_mask, inpt_lmask; /* [t] hash masks */
int inpt_count, inpt_size; /* [t] queue count, hash size */
};
/* flags in inp_flags: */
#define INP_RECVOPTS 0x001 /* receive incoming IP options */
#define INP_RECVRETOPTS 0x002 /* receive IP options for reply */
#define INP_RECVDSTADDR 0x004 /* receive IP dst address */
#define INP_RXDSTOPTS INP_RECVOPTS
#define INP_RXHOPOPTS INP_RECVRETOPTS
#define INP_RXINFO INP_RECVDSTADDR
#define INP_RXSRCRT 0x010
#define INP_HOPLIMIT 0x020
#define INP_HDRINCL 0x008 /* user supplies entire IP header */
#define INP_HIGHPORT 0x010 /* user wants "high" port binding */
#define INP_LOWPORT 0x020 /* user wants "low" port binding */
#define INP_RECVIF 0x080 /* receive incoming interface */
#define INP_RECVTTL 0x040 /* receive incoming IP TTL */
#define INP_RECVDSTPORT 0x200 /* receive IP dst addr before rdr */
#define INP_RECVRTABLE 0x400 /* receive routing table */
#define INP_IPSECFLOWINFO 0x800 /* receive IPsec flow info */
#define INP_CONTROLOPTS (INP_RECVOPTS|INP_RECVRETOPTS|INP_RECVDSTADDR| \
INP_RXSRCRT|INP_HOPLIMIT|INP_RECVIF|INP_RECVTTL|INP_RECVDSTPORT| \
INP_RECVRTABLE)
/*
* These flags' values should be determined by either the transport
* protocol at PRU_BIND, PRU_LISTEN, PRU_CONNECT, etc, or by in_pcb*().
*/
#define INP_IPV6 0x100 /* socket, proto, domain, family is PF_INET6 */
/*
* Flags in inp_flags for IPV6
*/
#define IN6P_HIGHPORT INP_HIGHPORT /* user wants "high" port */
#define IN6P_LOWPORT INP_LOWPORT /* user wants "low" port */
#define IN6P_RECVDSTPORT INP_RECVDSTPORT /* receive IP dst addr before rdr */
#define IN6P_PKTINFO 0x010000 /* receive IP6 dst and I/F */
#define IN6P_HOPLIMIT 0x020000 /* receive hoplimit */
#define IN6P_HOPOPTS 0x040000 /* receive hop-by-hop options */
#define IN6P_DSTOPTS 0x080000 /* receive dst options after rthdr */
#define IN6P_RTHDR 0x100000 /* receive routing header */
#define IN6P_TCLASS 0x400000 /* receive traffic class value */
#define IN6P_AUTOFLOWLABEL 0x800000 /* attach flowlabel automatically */
#define IN6P_ANONPORT 0x4000000 /* port chosen for user */
#define IN6P_RFC2292 0x40000000 /* used RFC2292 API on the socket */
#define IN6P_MTU 0x80000000 /* receive path MTU */
#define IN6P_MINMTU 0x20000000 /* use minimum MTU */
#define IN6P_CONTROLOPTS (IN6P_PKTINFO|IN6P_HOPLIMIT|IN6P_HOPOPTS|\
IN6P_DSTOPTS|IN6P_RTHDR|\
IN6P_TCLASS|IN6P_AUTOFLOWLABEL|IN6P_RFC2292|\
IN6P_MTU|IN6P_RECVDSTPORT)
#define INPLOOKUP_WILDCARD 1
#define INPLOOKUP_SETLOCAL 2
#define INPLOOKUP_IPV6 4
#define sotoinpcb(so) ((struct inpcb *)(so)->so_pcb)
/* macros for handling bitmap of ports not to allocate dynamically */
#define DP_MAPBITS (sizeof(u_int32_t) * NBBY)
#define DP_MAPSIZE (howmany(65536, DP_MAPBITS))
#define DP_SET(m, p) ((m)[(p) / DP_MAPBITS] |= (1U << ((p) % DP_MAPBITS)))
#define DP_CLR(m, p) ((m)[(p) / DP_MAPBITS] &= ~(1U << ((p) % DP_MAPBITS)))
#define DP_ISSET(m, p) ((m)[(p) / DP_MAPBITS] & (1U << ((p) % DP_MAPBITS)))
/* default values for baddynamicports [see ip_init()] */
#define DEFBADDYNAMICPORTS_TCP { \
587, 749, 750, 751, 853, 871, 2049, \
6000, 6001, 6002, 6003, 6004, 6005, 6006, 6007, 6008, 6009, 6010, \
0 }
#define DEFBADDYNAMICPORTS_UDP { 623, 664, 749, 750, 751, 2049, \
3784, 3785, 7784, /* BFD/S-BFD ports */ \
0 }
#define DEFROOTONLYPORTS_TCP { \
2049, \
0 }
#define DEFROOTONLYPORTS_UDP { \
2049, \
0 }
struct baddynamicports {
u_int32_t tcp[DP_MAPSIZE];
u_int32_t udp[DP_MAPSIZE];
};
#ifdef _KERNEL
#define IN_PCBLOCK_HOLD 1
#define IN_PCBLOCK_GRAB 2
extern struct inpcbtable rawcbtable, rawin6pcbtable;
extern struct baddynamicports baddynamicports;
extern struct baddynamicports rootonlyports;
extern int in_pcbnotifymiss;
void in_init(void);
void in_losing(struct inpcb *);
int in_pcballoc(struct socket *, struct inpcbtable *, int);
int in_pcbbind_locked(struct inpcb *, struct mbuf *, const void *,
struct proc *);
int in_pcbbind(struct inpcb *, struct mbuf *, struct proc *);
int in_pcbaddrisavail(const struct inpcb *, struct sockaddr_in *, int,
struct proc *);
int in_pcbconnect(struct inpcb *, struct mbuf *);
void in_pcbdetach(struct inpcb *);
struct inpcb *
in_pcbref(struct inpcb *);
void in_pcbunref(struct inpcb *);
void in_pcbdisconnect(struct inpcb *);
struct inpcb *
in_pcb_iterator(struct inpcbtable *, struct inpcb *,
struct inpcb_iterator *);
void in_pcb_iterator_abort(struct inpcbtable *, struct inpcb *,
struct inpcb_iterator *);
struct inpcb *
in_pcblookup(struct inpcbtable *, struct in_addr,
u_int, struct in_addr, u_int, u_int);
struct inpcb *
in_pcblookup_listen(struct inpcbtable *, struct in_addr, u_int,
struct mbuf *, u_int);
#ifdef INET6
uint64_t in6_pcbhash(struct inpcbtable *, u_int, const struct in6_addr *,
u_short, const struct in6_addr *, u_short);
struct inpcb *
in6_pcblookup(struct inpcbtable *, const struct in6_addr *,
u_int, const struct in6_addr *, u_int, u_int);
struct inpcb *
in6_pcblookup_listen(struct inpcbtable *, struct in6_addr *, u_int,
struct mbuf *, u_int);
int in6_pcbaddrisavail_lock(const struct inpcb *, struct sockaddr_in6 *,
int, struct proc *, int);
int in6_pcbaddrisavail(const struct inpcb *, struct sockaddr_in6 *, int,
struct proc *);
int in6_pcbconnect(struct inpcb *, struct mbuf *);
void in6_setsockaddr(struct inpcb *, struct mbuf *);
void in6_setpeeraddr(struct inpcb *, struct mbuf *);
int in6_sockaddr(struct socket *, struct mbuf *);
int in6_peeraddr(struct socket *, struct mbuf *);
#endif /* INET6 */
void in_pcbinit(struct inpcbtable *, int);
struct inpcb *
in_pcblookup_local_lock(struct inpcbtable *, const void *, u_int, int,
u_int, int);
void in_pcbnotifyall(struct inpcbtable *, const struct sockaddr_in *,
u_int, int, void (*)(struct inpcb *, int));
void in_pcbrehash(struct inpcb *);
void in_rtchange(struct inpcb *, int);
void in_setpeeraddr(struct inpcb *, struct mbuf *);
void in_setsockaddr(struct inpcb *, struct mbuf *);
int in_sockaddr(struct socket *, struct mbuf *);
int in_peeraddr(struct socket *, struct mbuf *);
int in_baddynamic(u_int16_t, u_int16_t);
int in_rootonly(u_int16_t, u_int16_t);
int in_pcbselsrc(struct in_addr *, struct sockaddr_in *, struct inpcb *);
struct rtentry *
in_pcbrtentry(struct inpcb *);
/* INET6 stuff */
struct rtentry *
in6_pcbrtentry(struct inpcb *);
void in6_pcbnotify(struct inpcbtable *, const struct sockaddr_in6 *,
u_int, const struct sockaddr_in6 *, u_int, u_int, int, void *,
void (*)(struct inpcb *, int));
int in6_selecthlim(const struct inpcb *);
int in_pcbset_rtableid(struct inpcb *, u_int);
void in_pcbset_laddr(struct inpcb *, const struct sockaddr *, u_int);
void in_pcbunset_faddr(struct inpcb *);
void in_pcbunset_laddr(struct inpcb *);
#endif /* _KERNEL */
#endif /* _NETINET_IN_PCB_H_ */
|