1c398230bSWarner Losh /*-
251369649SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
351369649SPedro F. Giffuni *
4df8bae1dSRodney W. Grimes * Copyright (c) 1982, 1986, 1988, 1993
50ae76120SRobert Watson * The Regents of the University of California.
60ae76120SRobert Watson * All rights reserved.
7df8bae1dSRodney W. Grimes *
8df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without
9df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions
10df8bae1dSRodney W. Grimes * are met:
11df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright
12df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer.
13df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright
14df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the
15df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution.
16fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors
17df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software
18df8bae1dSRodney W. Grimes * without specific prior written permission.
19df8bae1dSRodney W. Grimes *
20df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30df8bae1dSRodney W. Grimes * SUCH DAMAGE.
31df8bae1dSRodney W. Grimes */
32df8bae1dSRodney W. Grimes
334b421e2dSMike Silbersack #include <sys/cdefs.h>
3400c081e9SBjoern A. Zeeb #include "opt_inet.h"
356a800098SYoshinobu Inoue #include "opt_inet6.h"
366a800098SYoshinobu Inoue #include "opt_ipsec.h"
370c325f53SAlexander V. Chernikov #include "opt_route.h"
386a800098SYoshinobu Inoue
39df8bae1dSRodney W. Grimes #include <sys/param.h>
405a59cefcSBosko Milekic #include <sys/jail.h>
41117bcae7SGarrett Wollman #include <sys/kernel.h>
42ea8d1492SAlexander V. Chernikov #include <sys/eventhandler.h>
43960ed29cSSeigo Tanimura #include <sys/lock.h>
44df8bae1dSRodney W. Grimes #include <sys/malloc.h>
45df8bae1dSRodney W. Grimes #include <sys/mbuf.h>
46acd3428bSRobert Watson #include <sys/priv.h>
474787fd37SPaul Saab #include <sys/proc.h>
48df8bae1dSRodney W. Grimes #include <sys/protosw.h>
49385195c0SMarko Zec #include <sys/rwlock.h>
50960ed29cSSeigo Tanimura #include <sys/signalvar.h>
51117bcae7SGarrett Wollman #include <sys/socket.h>
52df8bae1dSRodney W. Grimes #include <sys/socketvar.h>
53960ed29cSSeigo Tanimura #include <sys/sx.h>
54117bcae7SGarrett Wollman #include <sys/sysctl.h>
55960ed29cSSeigo Tanimura #include <sys/systm.h>
568781d8e9SBruce Evans
5769c2d429SJeff Roberson #include <vm/uma.h>
58df8bae1dSRodney W. Grimes
59df8bae1dSRodney W. Grimes #include <net/if.h>
6076039bc8SGleb Smirnoff #include <net/if_var.h>
61df8bae1dSRodney W. Grimes #include <net/route.h>
6281728a53SAlexander V. Chernikov #include <net/route/route_ctl.h>
634b79449eSBjoern A. Zeeb #include <net/vnet.h>
64df8bae1dSRodney W. Grimes
65df8bae1dSRodney W. Grimes #include <netinet/in.h>
66df8bae1dSRodney W. Grimes #include <netinet/in_systm.h>
670c325f53SAlexander V. Chernikov #include <netinet/in_fib.h>
68c1f8a6ceSDavid Greenman #include <netinet/in_pcb.h>
69c1f8a6ceSDavid Greenman #include <netinet/in_var.h>
705b84dc78SQing Li #include <netinet/if_ether.h>
71960ed29cSSeigo Tanimura #include <netinet/ip.h>
72df8bae1dSRodney W. Grimes #include <netinet/ip_var.h>
73df8bae1dSRodney W. Grimes #include <netinet/ip_mroute.h>
746d7270a5SMichael Tuexen #include <netinet/ip_icmp.h>
75df8bae1dSRodney W. Grimes
76fcf59617SAndrey V. Elsukov #include <netipsec/ipsec_support.h>
77b9234fafSSam Leffler
7873d76e77SKevin Lo #include <machine/stdarg.h>
79aed55708SRobert Watson #include <security/mac/mac_framework.h>
80aed55708SRobert Watson
8178b1fc05SGleb Smirnoff extern ipproto_input_t *ip_protox[];
8278b1fc05SGleb Smirnoff
8374e9dcf7SBjoern A. Zeeb VNET_DEFINE(int, ip_defttl) = IPDEFTTL;
846df8a710SGleb Smirnoff SYSCTL_INT(_net_inet_ip, IPCTL_DEFTTL, ttl, CTLFLAG_VNET | CTLFLAG_RW,
8574e9dcf7SBjoern A. Zeeb &VNET_NAME(ip_defttl), 0,
8674e9dcf7SBjoern A. Zeeb "Maximum TTL on IP packets");
8774e9dcf7SBjoern A. Zeeb
88eddfbb76SRobert Watson VNET_DEFINE(struct inpcbinfo, ripcbinfo);
891e77c105SRobert Watson #define V_ripcbinfo VNET(ripcbinfo)
90df8bae1dSRodney W. Grimes
91115a40c7SLuigi Rizzo /*
92b2019e17SLuigi Rizzo * Control and data hooks for ipfw, dummynet, divert and so on.
93115a40c7SLuigi Rizzo * The data hooks are not used here but it is convenient
94115a40c7SLuigi Rizzo * to keep them all in one place.
95115a40c7SLuigi Rizzo */
960b4b0b0fSJulian Elischer VNET_DEFINE(ip_fw_ctl_ptr_t, ip_fw_ctl_ptr) = NULL;
97b2019e17SLuigi Rizzo
98b2019e17SLuigi Rizzo int (*ip_dn_ctl_ptr)(struct sockopt *);
99dc0fa4f7SGleb Smirnoff int (*ip_dn_io_ptr)(struct mbuf **, struct ip_fw_args *);
1001830dae3SGleb Smirnoff void (*ip_divert_ptr)(struct mbuf *, bool);
101cef9f220SGleb Smirnoff int (*ng_ipfw_input_p)(struct mbuf **, struct ip_fw_args *, bool);
102db69a05dSPaul Saab
10300c081e9SBjoern A. Zeeb #ifdef INET
104df8bae1dSRodney W. Grimes /*
1050ae76120SRobert Watson * Hooks for multicast routing. They all default to NULL, so leave them not
1060ae76120SRobert Watson * initialized and rely on BSS being set to 0.
107bbb4330bSLuigi Rizzo */
108bbb4330bSLuigi Rizzo
1090ae76120SRobert Watson /*
1100ae76120SRobert Watson * The socket used to communicate with the multicast routing daemon.
1110ae76120SRobert Watson */
112eddfbb76SRobert Watson VNET_DEFINE(struct socket *, ip_mrouter);
113bbb4330bSLuigi Rizzo
1140ae76120SRobert Watson /*
1150ae76120SRobert Watson * The various mrouter and rsvp functions.
1160ae76120SRobert Watson */
117bbb4330bSLuigi Rizzo int (*ip_mrouter_set)(struct socket *, struct sockopt *);
118bbb4330bSLuigi Rizzo int (*ip_mrouter_get)(struct socket *, struct sockopt *);
11977223d98SWojciech Macek int (*ip_mrouter_done)(void);
120bbb4330bSLuigi Rizzo int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *,
121bbb4330bSLuigi Rizzo struct ip_moptions *);
122e40bae9aSRoman Divacky int (*mrt_ioctl)(u_long, caddr_t, int);
123bbb4330bSLuigi Rizzo int (*legal_vif_num)(int);
124bbb4330bSLuigi Rizzo u_long (*ip_mcast_src)(int);
125bbb4330bSLuigi Rizzo
1268f5a8818SKevin Lo int (*rsvp_input_p)(struct mbuf **, int *, int);
127bbb4330bSLuigi Rizzo int (*ip_rsvp_vif)(struct socket *, struct sockopt *);
128bbb4330bSLuigi Rizzo void (*ip_rsvp_force_done)(struct socket *);
12900c081e9SBjoern A. Zeeb #endif /* INET */
13000c081e9SBjoern A. Zeeb
13100c081e9SBjoern A. Zeeb u_long rip_sendspace = 9216;
13200c081e9SBjoern A. Zeeb SYSCTL_ULONG(_net_inet_raw, OID_AUTO, maxdgram, CTLFLAG_RW,
13300c081e9SBjoern A. Zeeb &rip_sendspace, 0, "Maximum outgoing raw IP datagram size");
13400c081e9SBjoern A. Zeeb
13500c081e9SBjoern A. Zeeb u_long rip_recvspace = 9216;
13600c081e9SBjoern A. Zeeb SYSCTL_ULONG(_net_inet_raw, OID_AUTO, recvspace, CTLFLAG_RW,
13700c081e9SBjoern A. Zeeb &rip_recvspace, 0, "Maximum space for incoming raw IP datagrams");
138bbb4330bSLuigi Rizzo
139bbb4330bSLuigi Rizzo /*
1409ed324c9SAlexander Motin * Hash functions
1419ed324c9SAlexander Motin */
1429ed324c9SAlexander Motin
1439ed324c9SAlexander Motin #define INP_PCBHASH_RAW_SIZE 256
1449ed324c9SAlexander Motin #define INP_PCBHASH_RAW(proto, laddr, faddr, mask) \
1459ed324c9SAlexander Motin (((proto) + (laddr) + (faddr)) % (mask) + 1)
1469ed324c9SAlexander Motin
14700c081e9SBjoern A. Zeeb #ifdef INET
1489ed324c9SAlexander Motin static void
rip_inshash(struct inpcb * inp)1499ed324c9SAlexander Motin rip_inshash(struct inpcb *inp)
1509ed324c9SAlexander Motin {
1519ed324c9SAlexander Motin struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
1529ed324c9SAlexander Motin struct inpcbhead *pcbhash;
1539ed324c9SAlexander Motin int hash;
1549ed324c9SAlexander Motin
155db0ac6deSCy Schubert INP_HASH_WLOCK_ASSERT(pcbinfo);
1569ed324c9SAlexander Motin INP_WLOCK_ASSERT(inp);
1579ed324c9SAlexander Motin
15818f401c6SAlexander Motin if (inp->inp_ip_p != 0 &&
15918f401c6SAlexander Motin inp->inp_laddr.s_addr != INADDR_ANY &&
16018f401c6SAlexander Motin inp->inp_faddr.s_addr != INADDR_ANY) {
1619ed324c9SAlexander Motin hash = INP_PCBHASH_RAW(inp->inp_ip_p, inp->inp_laddr.s_addr,
1629ed324c9SAlexander Motin inp->inp_faddr.s_addr, pcbinfo->ipi_hashmask);
16318f401c6SAlexander Motin } else
1649ed324c9SAlexander Motin hash = 0;
165fdb987beSMark Johnston pcbhash = &pcbinfo->ipi_hash_exact[hash];
166fdb987beSMark Johnston CK_LIST_INSERT_HEAD(pcbhash, inp, inp_hash_exact);
1679ed324c9SAlexander Motin }
1689ed324c9SAlexander Motin
1699ed324c9SAlexander Motin static void
rip_delhash(struct inpcb * inp)1709ed324c9SAlexander Motin rip_delhash(struct inpcb *inp)
1719ed324c9SAlexander Motin {
17218f401c6SAlexander Motin
173db0ac6deSCy Schubert INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo);
1749ed324c9SAlexander Motin INP_WLOCK_ASSERT(inp);
17518f401c6SAlexander Motin
176fdb987beSMark Johnston CK_LIST_REMOVE(inp, inp_hash_exact);
1779ed324c9SAlexander Motin }
17800c081e9SBjoern A. Zeeb #endif /* INET */
1799ed324c9SAlexander Motin
1800aa120d5SGleb Smirnoff INPCBSTORAGE_DEFINE(ripcbstor, inpcb, "rawinp", "ripcb", "rip", "riphash");
181d915b280SStephan Uphoff
18289128ff3SGleb Smirnoff static void
rip_init(void * arg __unused)18389128ff3SGleb Smirnoff rip_init(void *arg __unused)
184df8bae1dSRodney W. Grimes {
185f2565d68SRobert Watson
186fec8a8c7SGleb Smirnoff in_pcbinfo_init(&V_ripcbinfo, &ripcbstor, INP_PCBHASH_RAW_SIZE, 1);
187df8bae1dSRodney W. Grimes }
18889128ff3SGleb Smirnoff VNET_SYSINIT(rip_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, rip_init, NULL);
189df8bae1dSRodney W. Grimes
190bc29160dSMarko Zec #ifdef VIMAGE
1913f58662dSBjoern A. Zeeb static void
rip_destroy(void * unused __unused)1923f58662dSBjoern A. Zeeb rip_destroy(void *unused __unused)
193bc29160dSMarko Zec {
194bc29160dSMarko Zec
1959bcd427bSRobert Watson in_pcbinfo_destroy(&V_ripcbinfo);
196bc29160dSMarko Zec }
1973f58662dSBjoern A. Zeeb VNET_SYSUNINIT(raw_ip, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, rip_destroy, NULL);
198bc29160dSMarko Zec #endif
199bc29160dSMarko Zec
20000c081e9SBjoern A. Zeeb #ifdef INET
2013b6dd5a9SSam Leffler static int
rip_append(struct inpcb * inp,struct ip * ip,struct mbuf * m,struct sockaddr_in * ripsrc)202db0ac6deSCy Schubert rip_append(struct inpcb *inp, struct ip *ip, struct mbuf *m,
2033b19fa35SRobert Watson struct sockaddr_in *ripsrc)
2043b6dd5a9SSam Leffler {
205db0ac6deSCy Schubert struct socket *so = inp->inp_socket;
206db0ac6deSCy Schubert struct mbuf *n, *opts = NULL;
20733841545SHajimu UMEMOTO
208db0ac6deSCy Schubert INP_LOCK_ASSERT(inp);
209cbe42d48SRobert Watson
210fcf59617SAndrey V. Elsukov #if defined(IPSEC) || defined(IPSEC_SUPPORT)
211da0f4099SHajimu UMEMOTO /* check AH/ESP integrity. */
212db0ac6deSCy Schubert if (IPSEC_ENABLED(ipv4) && IPSEC_CHECK_POLICY(ipv4, m, inp) != 0)
213db0ac6deSCy Schubert return (0);
214b2630c29SGeorge V. Neville-Neil #endif /* IPSEC */
2154ea889c6SRobert Watson #ifdef MAC
216db0ac6deSCy Schubert if (mac_inpcb_check_deliver(inp, m) != 0)
217db0ac6deSCy Schubert return (0);
2184ea889c6SRobert Watson #endif
219936cd18dSAndre Oppermann /* Check the minimum TTL for socket. */
220db0ac6deSCy Schubert if (inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl)
221db0ac6deSCy Schubert return (0);
2223b6dd5a9SSam Leffler
223db0ac6deSCy Schubert if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) == NULL)
224db0ac6deSCy Schubert return (0);
225db0ac6deSCy Schubert
226db0ac6deSCy Schubert if ((inp->inp_flags & INP_CONTROLOPTS) ||
2271fd7af26SAndre Oppermann (so->so_options & (SO_TIMESTAMP | SO_BINTIME)))
228db0ac6deSCy Schubert ip_savecontrol(inp, &opts, ip, n);
2291e4d7da7SRobert Watson SOCKBUF_LOCK(&so->so_rcv);
2301e4d7da7SRobert Watson if (sbappendaddr_locked(&so->so_rcv,
2313b19fa35SRobert Watson (struct sockaddr *)ripsrc, n, opts) == 0) {
2327045b160SRoy Marples soroverflow_locked(so);
233df8bae1dSRodney W. Grimes m_freem(n);
23482c23ebaSBill Fenner if (opts)
23582c23ebaSBill Fenner m_freem(opts);
236db0ac6deSCy Schubert return (0);
237db0ac6deSCy Schubert }
2381e4d7da7SRobert Watson sorwakeup_locked(so);
239db0ac6deSCy Schubert
240db0ac6deSCy Schubert return (1);
241db0ac6deSCy Schubert }
242db0ac6deSCy Schubert
243db0ac6deSCy Schubert struct rip_inp_match_ctx {
244db0ac6deSCy Schubert struct ip *ip;
245db0ac6deSCy Schubert int proto;
246db0ac6deSCy Schubert };
247db0ac6deSCy Schubert
248db0ac6deSCy Schubert static bool
rip_inp_match1(const struct inpcb * inp,void * v)249db0ac6deSCy Schubert rip_inp_match1(const struct inpcb *inp, void *v)
250db0ac6deSCy Schubert {
251db0ac6deSCy Schubert struct rip_inp_match_ctx *ctx = v;
252db0ac6deSCy Schubert
253db0ac6deSCy Schubert if (inp->inp_ip_p != ctx->proto)
254db0ac6deSCy Schubert return (false);
255db0ac6deSCy Schubert #ifdef INET6
256db0ac6deSCy Schubert /* XXX inp locking */
257db0ac6deSCy Schubert if ((inp->inp_vflag & INP_IPV4) == 0)
258db0ac6deSCy Schubert return (false);
259db0ac6deSCy Schubert #endif
260db0ac6deSCy Schubert if (inp->inp_laddr.s_addr != ctx->ip->ip_dst.s_addr)
261db0ac6deSCy Schubert return (false);
262db0ac6deSCy Schubert if (inp->inp_faddr.s_addr != ctx->ip->ip_src.s_addr)
263db0ac6deSCy Schubert return (false);
264db0ac6deSCy Schubert return (true);
265db0ac6deSCy Schubert }
266db0ac6deSCy Schubert
267db0ac6deSCy Schubert static bool
rip_inp_match2(const struct inpcb * inp,void * v)268db0ac6deSCy Schubert rip_inp_match2(const struct inpcb *inp, void *v)
269db0ac6deSCy Schubert {
270db0ac6deSCy Schubert struct rip_inp_match_ctx *ctx = v;
271db0ac6deSCy Schubert
272db0ac6deSCy Schubert if (inp->inp_ip_p && inp->inp_ip_p != ctx->proto)
273db0ac6deSCy Schubert return (false);
274db0ac6deSCy Schubert #ifdef INET6
275db0ac6deSCy Schubert /* XXX inp locking */
276db0ac6deSCy Schubert if ((inp->inp_vflag & INP_IPV4) == 0)
277db0ac6deSCy Schubert return (false);
278db0ac6deSCy Schubert #endif
279db0ac6deSCy Schubert if (!in_nullhost(inp->inp_laddr) &&
280db0ac6deSCy Schubert !in_hosteq(inp->inp_laddr, ctx->ip->ip_dst))
281db0ac6deSCy Schubert return (false);
282db0ac6deSCy Schubert if (!in_nullhost(inp->inp_faddr) &&
283db0ac6deSCy Schubert !in_hosteq(inp->inp_faddr, ctx->ip->ip_src))
284db0ac6deSCy Schubert return (false);
285db0ac6deSCy Schubert return (true);
286df8bae1dSRodney W. Grimes }
2873b6dd5a9SSam Leffler
2883b6dd5a9SSam Leffler /*
2890ae76120SRobert Watson * Setup generic address and protocol structures for raw_input routine, then
2900ae76120SRobert Watson * pass them along with mbuf chain.
2913b6dd5a9SSam Leffler */
2928f5a8818SKevin Lo int
rip_input(struct mbuf ** mp,int * offp,int proto)2938f5a8818SKevin Lo rip_input(struct mbuf **mp, int *offp, int proto)
2943b6dd5a9SSam Leffler {
295db0ac6deSCy Schubert struct rip_inp_match_ctx ctx = {
296db0ac6deSCy Schubert .ip = mtod(*mp, struct ip *),
297db0ac6deSCy Schubert .proto = proto,
298db0ac6deSCy Schubert };
299db0ac6deSCy Schubert struct inpcb_iterator inpi = INP_ITERATOR(&V_ripcbinfo,
300db0ac6deSCy Schubert INPLOOKUP_RLOCKPCB, rip_inp_match1, &ctx);
301d10910e6SBruce M Simpson struct ifnet *ifp;
3028f5a8818SKevin Lo struct mbuf *m = *mp;
303db0ac6deSCy Schubert struct inpcb *inp;
3043b19fa35SRobert Watson struct sockaddr_in ripsrc;
305db0ac6deSCy Schubert int appended;
306f42347c3SGleb Smirnoff
3078f5a8818SKevin Lo *mp = NULL;
308db0ac6deSCy Schubert appended = 0;
3098f5a8818SKevin Lo
3103b19fa35SRobert Watson bzero(&ripsrc, sizeof(ripsrc));
3113b19fa35SRobert Watson ripsrc.sin_len = sizeof(ripsrc);
3123b19fa35SRobert Watson ripsrc.sin_family = AF_INET;
313db0ac6deSCy Schubert ripsrc.sin_addr = ctx.ip->ip_src;
314d10910e6SBruce M Simpson
315d10910e6SBruce M Simpson ifp = m->m_pkthdr.rcvif;
316d10910e6SBruce M Simpson
317db0ac6deSCy Schubert inpi.hash = INP_PCBHASH_RAW(proto, ctx.ip->ip_src.s_addr,
318db0ac6deSCy Schubert ctx.ip->ip_dst.s_addr, V_ripcbinfo.ipi_hashmask);
319db0ac6deSCy Schubert while ((inp = inp_next(&inpi)) != NULL) {
320db0ac6deSCy Schubert INP_RLOCK_ASSERT(inp);
321db0ac6deSCy Schubert if (jailed_without_vnet(inp->inp_cred) &&
322db0ac6deSCy Schubert prison_check_ip4(inp->inp_cred, &ctx.ip->ip_dst) != 0) {
323e93fdbe2SMatt Macy /*
324e93fdbe2SMatt Macy * XXX: If faddr was bound to multicast group,
325e93fdbe2SMatt Macy * jailed raw socket will drop datagram.
326e93fdbe2SMatt Macy */
327db0ac6deSCy Schubert continue;
328266f97b5SCy Schubert }
329db0ac6deSCy Schubert appended += rip_append(inp, ctx.ip, m, &ripsrc);
330e5c331cfSMatt Macy }
331e93fdbe2SMatt Macy
332db0ac6deSCy Schubert inpi.hash = 0;
333db0ac6deSCy Schubert inpi.match = rip_inp_match2;
334db0ac6deSCy Schubert MPASS(inpi.inp == NULL);
335db0ac6deSCy Schubert while ((inp = inp_next(&inpi)) != NULL) {
336db0ac6deSCy Schubert INP_RLOCK_ASSERT(inp);
337db0ac6deSCy Schubert if (jailed_without_vnet(inp->inp_cred) &&
338db0ac6deSCy Schubert !IN_MULTICAST(ntohl(ctx.ip->ip_dst.s_addr)) &&
339db0ac6deSCy Schubert prison_check_ip4(inp->inp_cred, &ctx.ip->ip_dst) != 0)
340d10910e6SBruce M Simpson /*
341d10910e6SBruce M Simpson * Allow raw socket in jail to receive multicast;
342d10910e6SBruce M Simpson * assume process had PRIV_NETINET_RAW at attach,
343d10910e6SBruce M Simpson * and fall through into normal filter path if so.
344d10910e6SBruce M Simpson */
345db0ac6deSCy Schubert continue;
346d10910e6SBruce M Simpson /*
347d10910e6SBruce M Simpson * If this raw socket has multicast state, and we
348d10910e6SBruce M Simpson * have received a multicast, check if this socket
349d10910e6SBruce M Simpson * should receive it, as multicast filtering is now
350d10910e6SBruce M Simpson * the responsibility of the transport layer.
351d10910e6SBruce M Simpson */
352d10910e6SBruce M Simpson if (inp->inp_moptions != NULL &&
353db0ac6deSCy Schubert IN_MULTICAST(ntohl(ctx.ip->ip_dst.s_addr))) {
354793c7042SBruce M Simpson /*
355793c7042SBruce M Simpson * If the incoming datagram is for IGMP, allow it
356793c7042SBruce M Simpson * through unconditionally to the raw socket.
357793c7042SBruce M Simpson *
358793c7042SBruce M Simpson * In the case of IGMPv2, we may not have explicitly
359793c7042SBruce M Simpson * joined the group, and may have set IFF_ALLMULTI
360793c7042SBruce M Simpson * on the interface. imo_multi_filter() may discard
361793c7042SBruce M Simpson * control traffic we actually need to see.
362793c7042SBruce M Simpson *
363793c7042SBruce M Simpson * Userland multicast routing daemons should continue
364793c7042SBruce M Simpson * filter the control traffic appropriately.
365793c7042SBruce M Simpson */
366d10910e6SBruce M Simpson int blocked;
367d10910e6SBruce M Simpson
368793c7042SBruce M Simpson blocked = MCAST_PASS;
369793c7042SBruce M Simpson if (proto != IPPROTO_IGMP) {
370793c7042SBruce M Simpson struct sockaddr_in group;
371793c7042SBruce M Simpson
372d10910e6SBruce M Simpson bzero(&group, sizeof(struct sockaddr_in));
373d10910e6SBruce M Simpson group.sin_len = sizeof(struct sockaddr_in);
374d10910e6SBruce M Simpson group.sin_family = AF_INET;
375db0ac6deSCy Schubert group.sin_addr = ctx.ip->ip_dst;
376d10910e6SBruce M Simpson
377793c7042SBruce M Simpson blocked = imo_multi_filter(inp->inp_moptions,
378793c7042SBruce M Simpson ifp,
379d10910e6SBruce M Simpson (struct sockaddr *)&group,
380d10910e6SBruce M Simpson (struct sockaddr *)&ripsrc);
381793c7042SBruce M Simpson }
382793c7042SBruce M Simpson
383d10910e6SBruce M Simpson if (blocked != MCAST_PASS) {
38486425c62SRobert Watson IPSTAT_INC(ips_notmember);
385e93fdbe2SMatt Macy continue;
386df8bae1dSRodney W. Grimes }
387db0ac6deSCy Schubert }
388db0ac6deSCy Schubert appended += rip_append(inp, ctx.ip, m, &ripsrc);
389db0ac6deSCy Schubert }
39078b1fc05SGleb Smirnoff if (appended == 0 && ip_protox[ctx.ip->ip_p] == rip_input) {
39186425c62SRobert Watson IPSTAT_INC(ips_noproto);
39286425c62SRobert Watson IPSTAT_DEC(ips_delivered);
3936d7270a5SMichael Tuexen icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL, 0, 0);
394db0ac6deSCy Schubert } else
395ad2cbb09SMichael Tuexen m_freem(m);
3968f5a8818SKevin Lo return (IPPROTO_DONE);
397df8bae1dSRodney W. Grimes }
398df8bae1dSRodney W. Grimes
399df8bae1dSRodney W. Grimes /*
4000ae76120SRobert Watson * Generate IP header and pass packet to ip_output. Tack on options user may
4010ae76120SRobert Watson * have setup with control call.
402df8bae1dSRodney W. Grimes */
4033d2041c0SGleb Smirnoff static int
rip_send(struct socket * so,int pruflags,struct mbuf * m,struct sockaddr * nam,struct mbuf * control,struct thread * td)4043d2041c0SGleb Smirnoff rip_send(struct socket *so, int pruflags, struct mbuf *m, struct sockaddr *nam,
4053d2041c0SGleb Smirnoff struct mbuf *control, struct thread *td)
406df8bae1dSRodney W. Grimes {
407b9555453SGleb Smirnoff struct epoch_tracker et;
4083b6dd5a9SSam Leffler struct ip *ip;
4093d2041c0SGleb Smirnoff struct inpcb *inp;
4103d2041c0SGleb Smirnoff in_addr_t *dst;
4113d2041c0SGleb Smirnoff int error, flags, cnt, hlen;
412aef06417SMichael Tuexen u_char opttype, optlen, *cp;
413df8bae1dSRodney W. Grimes
4143d2041c0SGleb Smirnoff inp = sotoinpcb(so);
4153d2041c0SGleb Smirnoff KASSERT(inp != NULL, ("rip_send: inp == NULL"));
4163d2041c0SGleb Smirnoff
4173d2041c0SGleb Smirnoff if (control != NULL) {
4183d2041c0SGleb Smirnoff m_freem(control);
4193d2041c0SGleb Smirnoff control = NULL;
4203d2041c0SGleb Smirnoff }
4213d2041c0SGleb Smirnoff
4223d2041c0SGleb Smirnoff if (so->so_state & SS_ISCONNECTED) {
4233d2041c0SGleb Smirnoff if (nam) {
4243d2041c0SGleb Smirnoff error = EISCONN;
4253d2041c0SGleb Smirnoff m_freem(m);
4263d2041c0SGleb Smirnoff return (error);
4273d2041c0SGleb Smirnoff }
4283d2041c0SGleb Smirnoff dst = &inp->inp_faddr.s_addr;
4293d2041c0SGleb Smirnoff } else {
4303d2041c0SGleb Smirnoff if (nam == NULL)
4313d2041c0SGleb Smirnoff error = ENOTCONN;
4323d2041c0SGleb Smirnoff else if (nam->sa_family != AF_INET)
4333d2041c0SGleb Smirnoff error = EAFNOSUPPORT;
4343d2041c0SGleb Smirnoff else if (nam->sa_len != sizeof(struct sockaddr_in))
4353d2041c0SGleb Smirnoff error = EINVAL;
4363d2041c0SGleb Smirnoff else
4373d2041c0SGleb Smirnoff error = 0;
4383d2041c0SGleb Smirnoff if (error != 0) {
4393d2041c0SGleb Smirnoff m_freem(m);
4403d2041c0SGleb Smirnoff return (error);
4413d2041c0SGleb Smirnoff }
4423d2041c0SGleb Smirnoff dst = &((struct sockaddr_in *)nam)->sin_addr.s_addr;
4433d2041c0SGleb Smirnoff }
4443d2041c0SGleb Smirnoff
4453d2041c0SGleb Smirnoff flags = ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0) |
4463d2041c0SGleb Smirnoff IP_ALLOWBROADCAST;
44773d76e77SKevin Lo
448df8bae1dSRodney W. Grimes /*
4490ae76120SRobert Watson * If the user handed us a complete IP packet, use it. Otherwise,
4500ae76120SRobert Watson * allocate an mbuf for a header and fill it in.
451df8bae1dSRodney W. Grimes */
452df8bae1dSRodney W. Grimes if ((inp->inp_flags & INP_HDRINCL) == 0) {
453430d30d8SBill Fenner if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) {
454430d30d8SBill Fenner m_freem(m);
455430d30d8SBill Fenner return(EMSGSIZE);
456430d30d8SBill Fenner }
457eb1b1807SGleb Smirnoff M_PREPEND(m, sizeof(struct ip), M_NOWAIT);
4586b48911bSRobert Watson if (m == NULL)
4596b48911bSRobert Watson return(ENOBUFS);
460ac830b58SBosko Milekic
4619ad11dd8SRobert Watson INP_RLOCK(inp);
462df8bae1dSRodney W. Grimes ip = mtod(m, struct ip *);
4638ce3f3ddSRuslan Ermilov ip->ip_tos = inp->inp_ip_tos;
464b2828ad2SAndre Oppermann if (inp->inp_flags & INP_DONTFRAG)
4658f134647SGleb Smirnoff ip->ip_off = htons(IP_DF);
466b2828ad2SAndre Oppermann else
4678f134647SGleb Smirnoff ip->ip_off = htons(0);
468ca98b82cSDavid Greenman ip->ip_p = inp->inp_ip_p;
4698f134647SGleb Smirnoff ip->ip_len = htons(m->m_pkthdr.len);
470b89e82ddSJamie Gritton ip->ip_src = inp->inp_laddr;
4713d2041c0SGleb Smirnoff ip->ip_dst.s_addr = *dst;
4720c325f53SAlexander V. Chernikov #ifdef ROUTE_MPATH
4730c325f53SAlexander V. Chernikov if (CALC_FLOWID_OUTBOUND) {
4740c325f53SAlexander V. Chernikov uint32_t hash_type, hash_val;
4750c325f53SAlexander V. Chernikov
4760c325f53SAlexander V. Chernikov hash_val = fib4_calc_software_hash(ip->ip_src,
4770c325f53SAlexander V. Chernikov ip->ip_dst, 0, 0, ip->ip_p, &hash_type);
4780c325f53SAlexander V. Chernikov m->m_pkthdr.flowid = hash_val;
4790c325f53SAlexander V. Chernikov M_HASHTYPE_SET(m, hash_type);
4800c325f53SAlexander V. Chernikov flags |= IP_NODEFAULTFLOWID;
4810c325f53SAlexander V. Chernikov }
4820c325f53SAlexander V. Chernikov #endif
4837a657e63SBjoern A. Zeeb if (jailed(inp->inp_cred)) {
4847a657e63SBjoern A. Zeeb /*
4857a657e63SBjoern A. Zeeb * prison_local_ip4() would be good enough but would
4867a657e63SBjoern A. Zeeb * let a source of INADDR_ANY pass, which we do not
487ae190832SSteven Hartland * want to see from jails.
4887a657e63SBjoern A. Zeeb */
489ae190832SSteven Hartland if (ip->ip_src.s_addr == INADDR_ANY) {
490c1604fe4SGleb Smirnoff NET_EPOCH_ENTER(et);
491c1604fe4SGleb Smirnoff error = in_pcbladdr(inp, &ip->ip_dst,
492c1604fe4SGleb Smirnoff &ip->ip_src, inp->inp_cred);
493c1604fe4SGleb Smirnoff NET_EPOCH_EXIT(et);
494ae190832SSteven Hartland } else {
4957a657e63SBjoern A. Zeeb error = prison_local_ip4(inp->inp_cred,
4967a657e63SBjoern A. Zeeb &ip->ip_src);
497ae190832SSteven Hartland }
498b89e82ddSJamie Gritton if (error != 0) {
499413628a7SBjoern A. Zeeb INP_RUNLOCK(inp);
500413628a7SBjoern A. Zeeb m_freem(m);
501b89e82ddSJamie Gritton return (error);
502413628a7SBjoern A. Zeeb }
5037a657e63SBjoern A. Zeeb }
5048ce3f3ddSRuslan Ermilov ip->ip_ttl = inp->inp_ip_ttl;
505df8bae1dSRodney W. Grimes } else {
506430d30d8SBill Fenner if (m->m_pkthdr.len > IP_MAXPACKET) {
507430d30d8SBill Fenner m_freem(m);
508430d30d8SBill Fenner return (EMSGSIZE);
509430d30d8SBill Fenner }
510ba218252SMark Johnston if (m->m_pkthdr.len < sizeof(*ip)) {
511ba218252SMark Johnston m_freem(m);
512ba218252SMark Johnston return (EINVAL);
513ba218252SMark Johnston }
514ba218252SMark Johnston m = m_pullup(m, sizeof(*ip));
515ba218252SMark Johnston if (m == NULL)
516ba218252SMark Johnston return (ENOMEM);
517df8bae1dSRodney W. Grimes ip = mtod(m, struct ip *);
51820a6a3a7SMichael Tuexen hlen = ip->ip_hl << 2;
51920a6a3a7SMichael Tuexen if (m->m_len < hlen) {
52020a6a3a7SMichael Tuexen m = m_pullup(m, hlen);
52120a6a3a7SMichael Tuexen if (m == NULL)
52220a6a3a7SMichael Tuexen return (EINVAL);
52320a6a3a7SMichael Tuexen ip = mtod(m, struct ip *);
52420a6a3a7SMichael Tuexen }
5250c325f53SAlexander V. Chernikov #ifdef ROUTE_MPATH
5260c325f53SAlexander V. Chernikov if (CALC_FLOWID_OUTBOUND) {
5270c325f53SAlexander V. Chernikov uint32_t hash_type, hash_val;
52820a6a3a7SMichael Tuexen
5290c325f53SAlexander V. Chernikov hash_val = fib4_calc_software_hash(ip->ip_dst,
5300c325f53SAlexander V. Chernikov ip->ip_src, 0, 0, ip->ip_p, &hash_type);
5310c325f53SAlexander V. Chernikov m->m_pkthdr.flowid = hash_val;
5320c325f53SAlexander V. Chernikov M_HASHTYPE_SET(m, hash_type);
5330c325f53SAlexander V. Chernikov flags |= IP_NODEFAULTFLOWID;
5340c325f53SAlexander V. Chernikov }
5350c325f53SAlexander V. Chernikov #endif
53620a6a3a7SMichael Tuexen INP_RLOCK(inp);
53720a6a3a7SMichael Tuexen /*
53820a6a3a7SMichael Tuexen * Don't allow both user specified and setsockopt options,
53920a6a3a7SMichael Tuexen * and don't allow packet length sizes that will crash.
54020a6a3a7SMichael Tuexen */
54120a6a3a7SMichael Tuexen if ((hlen < sizeof (*ip))
54220a6a3a7SMichael Tuexen || ((hlen > sizeof (*ip)) && inp->inp_options)
54320a6a3a7SMichael Tuexen || (ntohs(ip->ip_len) != m->m_pkthdr.len)) {
54420a6a3a7SMichael Tuexen INP_RUNLOCK(inp);
54520a6a3a7SMichael Tuexen m_freem(m);
54620a6a3a7SMichael Tuexen return (EINVAL);
54720a6a3a7SMichael Tuexen }
548b89e82ddSJamie Gritton error = prison_check_ip4(inp->inp_cred, &ip->ip_src);
549b89e82ddSJamie Gritton if (error != 0) {
5509ad11dd8SRobert Watson INP_RUNLOCK(inp);
5515a59cefcSBosko Milekic m_freem(m);
552b89e82ddSJamie Gritton return (error);
5535a59cefcSBosko Milekic }
5546d947416SGleb Smirnoff /*
555aef06417SMichael Tuexen * Don't allow IP options which do not have the required
556aef06417SMichael Tuexen * structure as specified in section 3.1 of RFC 791 on
557aef06417SMichael Tuexen * pages 15-23.
558aef06417SMichael Tuexen */
559aef06417SMichael Tuexen cp = (u_char *)(ip + 1);
56020a6a3a7SMichael Tuexen cnt = hlen - sizeof (struct ip);
561aef06417SMichael Tuexen for (; cnt > 0; cnt -= optlen, cp += optlen) {
562aef06417SMichael Tuexen opttype = cp[IPOPT_OPTVAL];
563aef06417SMichael Tuexen if (opttype == IPOPT_EOL)
564aef06417SMichael Tuexen break;
565aef06417SMichael Tuexen if (opttype == IPOPT_NOP) {
566aef06417SMichael Tuexen optlen = 1;
567aef06417SMichael Tuexen continue;
568aef06417SMichael Tuexen }
569aef06417SMichael Tuexen if (cnt < IPOPT_OLEN + sizeof(u_char)) {
570aef06417SMichael Tuexen INP_RUNLOCK(inp);
571aef06417SMichael Tuexen m_freem(m);
572aef06417SMichael Tuexen return (EINVAL);
573aef06417SMichael Tuexen }
574aef06417SMichael Tuexen optlen = cp[IPOPT_OLEN];
575aef06417SMichael Tuexen if (optlen < IPOPT_OLEN + sizeof(u_char) ||
576aef06417SMichael Tuexen optlen > cnt) {
577aef06417SMichael Tuexen INP_RUNLOCK(inp);
578aef06417SMichael Tuexen m_freem(m);
579aef06417SMichael Tuexen return (EINVAL);
580aef06417SMichael Tuexen }
581aef06417SMichael Tuexen }
582aef06417SMichael Tuexen /*
5836d947416SGleb Smirnoff * This doesn't allow application to specify ID of zero,
5846d947416SGleb Smirnoff * but we got this limitation from the beginning of history.
5856d947416SGleb Smirnoff */
586df8bae1dSRodney W. Grimes if (ip->ip_id == 0)
5876d947416SGleb Smirnoff ip_fillid(ip);
5880ae76120SRobert Watson
5890ae76120SRobert Watson /*
5900ae76120SRobert Watson * XXX prevent ip_output from overwriting header fields.
5910ae76120SRobert Watson */
592df8bae1dSRodney W. Grimes flags |= IP_RAWOUTPUT;
59386425c62SRobert Watson IPSTAT_INC(ips_rawout);
594df8bae1dSRodney W. Grimes }
5956a800098SYoshinobu Inoue
5966fbfd582SAndre Oppermann if (inp->inp_flags & INP_ONESBCAST)
5978afa2304SBruce M Simpson flags |= IP_SENDONES;
5988afa2304SBruce M Simpson
599ac830b58SBosko Milekic #ifdef MAC
60030d239bcSRobert Watson mac_inpcb_create_mbuf(inp, m);
601ac830b58SBosko Milekic #endif
602ac830b58SBosko Milekic
603b9555453SGleb Smirnoff NET_EPOCH_ENTER(et);
604ac830b58SBosko Milekic error = ip_output(m, inp->inp_options, NULL, flags,
605ac830b58SBosko Milekic inp->inp_moptions, inp);
606b9555453SGleb Smirnoff NET_EPOCH_EXIT(et);
6079ad11dd8SRobert Watson INP_RUNLOCK(inp);
6080ae76120SRobert Watson return (error);
609df8bae1dSRodney W. Grimes }
610df8bae1dSRodney W. Grimes
611df8bae1dSRodney W. Grimes /*
612df8bae1dSRodney W. Grimes * Raw IP socket option processing.
61383503a92SRobert Watson *
6146c67b8b6SRobert Watson * IMPORTANT NOTE regarding access control: Traditionally, raw sockets could
6156c67b8b6SRobert Watson * only be created by a privileged process, and as such, socket option
6166c67b8b6SRobert Watson * operations to manage system properties on any raw socket were allowed to
6176c67b8b6SRobert Watson * take place without explicit additional access control checks. However,
6186c67b8b6SRobert Watson * raw sockets can now also be created in jail(), and therefore explicit
6196c67b8b6SRobert Watson * checks are now required. Likewise, raw sockets can be used by a process
6206c67b8b6SRobert Watson * after it gives up privilege, so some caution is required. For options
6216c67b8b6SRobert Watson * passed down to the IP layer via ip_ctloutput(), checks are assumed to be
6226c67b8b6SRobert Watson * performed in ip_ctloutput() and therefore no check occurs here.
62302dd4b5cSRobert Watson * Unilaterally checking priv_check() here breaks normal IP socket option
6246c67b8b6SRobert Watson * operations on raw sockets.
6256c67b8b6SRobert Watson *
6266c67b8b6SRobert Watson * When adding new socket options here, make sure to add access control
6276c67b8b6SRobert Watson * checks here as necessary.
628762ad1d6SBjoern A. Zeeb *
629762ad1d6SBjoern A. Zeeb * XXX-BZ inp locking?
630df8bae1dSRodney W. Grimes */
631df8bae1dSRodney W. Grimes int
rip_ctloutput(struct socket * so,struct sockopt * sopt)6323b6dd5a9SSam Leffler rip_ctloutput(struct socket *so, struct sockopt *sopt)
633df8bae1dSRodney W. Grimes {
634cfe8b629SGarrett Wollman struct inpcb *inp = sotoinpcb(so);
635cfe8b629SGarrett Wollman int error, optval;
636df8bae1dSRodney W. Grimes
637bc97ba51SJulian Elischer if (sopt->sopt_level != IPPROTO_IP) {
638bc97ba51SJulian Elischer if ((sopt->sopt_level == SOL_SOCKET) &&
639bc97ba51SJulian Elischer (sopt->sopt_name == SO_SETFIB)) {
640bc97ba51SJulian Elischer inp->inp_inc.inc_fibnum = so->so_fibnum;
641bc97ba51SJulian Elischer return (0);
642bc97ba51SJulian Elischer }
643df8bae1dSRodney W. Grimes return (EINVAL);
644bc97ba51SJulian Elischer }
645df8bae1dSRodney W. Grimes
64625f26ad8SGarrett Wollman error = 0;
647cfe8b629SGarrett Wollman switch (sopt->sopt_dir) {
648cfe8b629SGarrett Wollman case SOPT_GET:
649cfe8b629SGarrett Wollman switch (sopt->sopt_name) {
650cfe8b629SGarrett Wollman case IP_HDRINCL:
651cfe8b629SGarrett Wollman optval = inp->inp_flags & INP_HDRINCL;
652cfe8b629SGarrett Wollman error = sooptcopyout(sopt, &optval, sizeof optval);
653cfe8b629SGarrett Wollman break;
654df8bae1dSRodney W. Grimes
6553429911dSLuigi Rizzo case IP_FW3: /* generic ipfw v.3 functions */
6567b109fa4SLuigi Rizzo case IP_FW_ADD: /* ADD actually returns the body... */
65709bb5f75SPoul-Henning Kamp case IP_FW_GET:
658cd8b5ae0SRuslan Ermilov case IP_FW_TABLE_GETSIZE:
659cd8b5ae0SRuslan Ermilov case IP_FW_TABLE_LIST:
660ff2f6fe8SPaolo Pisati case IP_FW_NAT_GET_CONFIG:
661ff2f6fe8SPaolo Pisati case IP_FW_NAT_GET_LOG:
6620b4b0b0fSJulian Elischer if (V_ip_fw_ctl_ptr != NULL)
6630b4b0b0fSJulian Elischer error = V_ip_fw_ctl_ptr(sopt);
6647b109fa4SLuigi Rizzo else
6657b109fa4SLuigi Rizzo error = ENOPROTOOPT;
666cfe8b629SGarrett Wollman break;
6674dd1662bSUgen J.S. Antsilevich
6683429911dSLuigi Rizzo case IP_DUMMYNET3: /* generic dummynet v.3 functions */
669b715f178SLuigi Rizzo case IP_DUMMYNET_GET:
6709b932e9eSAndre Oppermann if (ip_dn_ctl_ptr != NULL)
671b715f178SLuigi Rizzo error = ip_dn_ctl_ptr(sopt);
6727b109fa4SLuigi Rizzo else
6737b109fa4SLuigi Rizzo error = ENOPROTOOPT;
674b715f178SLuigi Rizzo break ;
6751c5de19aSGarrett Wollman
6761c5de19aSGarrett Wollman case MRT_INIT:
6771c5de19aSGarrett Wollman case MRT_DONE:
6781c5de19aSGarrett Wollman case MRT_ADD_VIF:
6791c5de19aSGarrett Wollman case MRT_DEL_VIF:
6801c5de19aSGarrett Wollman case MRT_ADD_MFC:
6811c5de19aSGarrett Wollman case MRT_DEL_MFC:
6821c5de19aSGarrett Wollman case MRT_VERSION:
6831c5de19aSGarrett Wollman case MRT_ASSERT:
6841e78ac21SJeffrey Hsu case MRT_API_SUPPORT:
6851e78ac21SJeffrey Hsu case MRT_API_CONFIG:
6861e78ac21SJeffrey Hsu case MRT_ADD_BW_UPCALL:
6871e78ac21SJeffrey Hsu case MRT_DEL_BW_UPCALL:
688acd3428bSRobert Watson error = priv_check(curthread, PRIV_NETINET_MROUTE);
6896c67b8b6SRobert Watson if (error != 0)
6906c67b8b6SRobert Watson return (error);
69174ed2e8aSGleb Smirnoff if (inp->inp_ip_p != IPPROTO_IGMP)
69274ed2e8aSGleb Smirnoff return (EOPNOTSUPP);
693bbb4330bSLuigi Rizzo error = ip_mrouter_get ? ip_mrouter_get(so, sopt) :
694bbb4330bSLuigi Rizzo EOPNOTSUPP;
695cfe8b629SGarrett Wollman break;
696cfe8b629SGarrett Wollman
697cfe8b629SGarrett Wollman default:
698cfe8b629SGarrett Wollman error = ip_ctloutput(so, sopt);
699cfe8b629SGarrett Wollman break;
700df8bae1dSRodney W. Grimes }
701cfe8b629SGarrett Wollman break;
702cfe8b629SGarrett Wollman
703cfe8b629SGarrett Wollman case SOPT_SET:
704cfe8b629SGarrett Wollman switch (sopt->sopt_name) {
705cfe8b629SGarrett Wollman case IP_HDRINCL:
706cfe8b629SGarrett Wollman error = sooptcopyin(sopt, &optval, sizeof optval,
707cfe8b629SGarrett Wollman sizeof optval);
708cfe8b629SGarrett Wollman if (error)
709cfe8b629SGarrett Wollman break;
710cfe8b629SGarrett Wollman if (optval)
711cfe8b629SGarrett Wollman inp->inp_flags |= INP_HDRINCL;
712cfe8b629SGarrett Wollman else
713cfe8b629SGarrett Wollman inp->inp_flags &= ~INP_HDRINCL;
714cfe8b629SGarrett Wollman break;
715cfe8b629SGarrett Wollman
7163429911dSLuigi Rizzo case IP_FW3: /* generic ipfw v.3 functions */
7178ba03966SRuslan Ermilov case IP_FW_ADD:
718cfe8b629SGarrett Wollman case IP_FW_DEL:
719cfe8b629SGarrett Wollman case IP_FW_FLUSH:
720cfe8b629SGarrett Wollman case IP_FW_ZERO:
7210b6c1a83SBrian Feldman case IP_FW_RESETLOG:
722cd8b5ae0SRuslan Ermilov case IP_FW_TABLE_ADD:
723cd8b5ae0SRuslan Ermilov case IP_FW_TABLE_DEL:
724cd8b5ae0SRuslan Ermilov case IP_FW_TABLE_FLUSH:
725ff2f6fe8SPaolo Pisati case IP_FW_NAT_CFG:
726ff2f6fe8SPaolo Pisati case IP_FW_NAT_DEL:
7270b4b0b0fSJulian Elischer if (V_ip_fw_ctl_ptr != NULL)
7280b4b0b0fSJulian Elischer error = V_ip_fw_ctl_ptr(sopt);
7297b109fa4SLuigi Rizzo else
7307b109fa4SLuigi Rizzo error = ENOPROTOOPT;
731cfe8b629SGarrett Wollman break;
732cfe8b629SGarrett Wollman
7333429911dSLuigi Rizzo case IP_DUMMYNET3: /* generic dummynet v.3 functions */
734b715f178SLuigi Rizzo case IP_DUMMYNET_CONFIGURE:
735b715f178SLuigi Rizzo case IP_DUMMYNET_DEL:
736b715f178SLuigi Rizzo case IP_DUMMYNET_FLUSH:
7379b932e9eSAndre Oppermann if (ip_dn_ctl_ptr != NULL)
738b715f178SLuigi Rizzo error = ip_dn_ctl_ptr(sopt);
7397b109fa4SLuigi Rizzo else
7407b109fa4SLuigi Rizzo error = ENOPROTOOPT ;
741b715f178SLuigi Rizzo break ;
742cfe8b629SGarrett Wollman
743cfe8b629SGarrett Wollman case IP_RSVP_ON:
744acd3428bSRobert Watson error = priv_check(curthread, PRIV_NETINET_MROUTE);
7456c67b8b6SRobert Watson if (error != 0)
7466c67b8b6SRobert Watson return (error);
74774ed2e8aSGleb Smirnoff if (inp->inp_ip_p != IPPROTO_RSVP)
74874ed2e8aSGleb Smirnoff return (EOPNOTSUPP);
749cfe8b629SGarrett Wollman error = ip_rsvp_init(so);
750cfe8b629SGarrett Wollman break;
751cfe8b629SGarrett Wollman
752cfe8b629SGarrett Wollman case IP_RSVP_OFF:
753acd3428bSRobert Watson error = priv_check(curthread, PRIV_NETINET_MROUTE);
7546c67b8b6SRobert Watson if (error != 0)
7556c67b8b6SRobert Watson return (error);
756cfe8b629SGarrett Wollman error = ip_rsvp_done();
757cfe8b629SGarrett Wollman break;
758cfe8b629SGarrett Wollman
759cfe8b629SGarrett Wollman case IP_RSVP_VIF_ON:
760cfe8b629SGarrett Wollman case IP_RSVP_VIF_OFF:
761acd3428bSRobert Watson error = priv_check(curthread, PRIV_NETINET_MROUTE);
7626c67b8b6SRobert Watson if (error != 0)
7636c67b8b6SRobert Watson return (error);
76474ed2e8aSGleb Smirnoff if (inp->inp_ip_p != IPPROTO_RSVP)
76574ed2e8aSGleb Smirnoff return (EOPNOTSUPP);
766bbb4330bSLuigi Rizzo error = ip_rsvp_vif ?
767bbb4330bSLuigi Rizzo ip_rsvp_vif(so, sopt) : EINVAL;
768cfe8b629SGarrett Wollman break;
769cfe8b629SGarrett Wollman
770cfe8b629SGarrett Wollman case MRT_INIT:
771cfe8b629SGarrett Wollman case MRT_DONE:
772cfe8b629SGarrett Wollman case MRT_ADD_VIF:
773cfe8b629SGarrett Wollman case MRT_DEL_VIF:
774cfe8b629SGarrett Wollman case MRT_ADD_MFC:
775cfe8b629SGarrett Wollman case MRT_DEL_MFC:
776cfe8b629SGarrett Wollman case MRT_VERSION:
777cfe8b629SGarrett Wollman case MRT_ASSERT:
7781e78ac21SJeffrey Hsu case MRT_API_SUPPORT:
7791e78ac21SJeffrey Hsu case MRT_API_CONFIG:
7801e78ac21SJeffrey Hsu case MRT_ADD_BW_UPCALL:
7811e78ac21SJeffrey Hsu case MRT_DEL_BW_UPCALL:
782acd3428bSRobert Watson error = priv_check(curthread, PRIV_NETINET_MROUTE);
7836c67b8b6SRobert Watson if (error != 0)
7846c67b8b6SRobert Watson return (error);
78574ed2e8aSGleb Smirnoff if (inp->inp_ip_p != IPPROTO_IGMP)
78674ed2e8aSGleb Smirnoff return (EOPNOTSUPP);
787bbb4330bSLuigi Rizzo error = ip_mrouter_set ? ip_mrouter_set(so, sopt) :
788bbb4330bSLuigi Rizzo EOPNOTSUPP;
789cfe8b629SGarrett Wollman break;
790cfe8b629SGarrett Wollman
791cfe8b629SGarrett Wollman default:
792cfe8b629SGarrett Wollman error = ip_ctloutput(so, sopt);
793cfe8b629SGarrett Wollman break;
794cfe8b629SGarrett Wollman }
795cfe8b629SGarrett Wollman break;
796cfe8b629SGarrett Wollman }
797cfe8b629SGarrett Wollman
798cfe8b629SGarrett Wollman return (error);
799df8bae1dSRodney W. Grimes }
800df8bae1dSRodney W. Grimes
80139191c8eSGarrett Wollman void
rip_ctlinput(struct icmp * icmp)802fcb3f813SGleb Smirnoff rip_ctlinput(struct icmp *icmp)
80339191c8eSGarrett Wollman {
804d9d59bb1SWojciech Macek #if defined(IPSEC) || defined(IPSEC_SUPPORT)
805d9d59bb1SWojciech Macek if (IPSEC_ENABLED(ipv4))
806fcb3f813SGleb Smirnoff IPSEC_CTLINPUT(ipv4, icmp);
807d9d59bb1SWojciech Macek #endif
80839191c8eSGarrett Wollman }
80939191c8eSGarrett Wollman
810117bcae7SGarrett Wollman static int
rip_attach(struct socket * so,int proto,struct thread * td)811b40ce416SJulian Elischer rip_attach(struct socket *so, int proto, struct thread *td)
812df8bae1dSRodney W. Grimes {
813117bcae7SGarrett Wollman struct inpcb *inp;
8143b6dd5a9SSam Leffler int error;
815c1f8a6ceSDavid Greenman
816117bcae7SGarrett Wollman inp = sotoinpcb(so);
81714ba8addSRobert Watson KASSERT(inp == NULL, ("rip_attach: inp != NULL"));
81832f9753cSRobert Watson
81932f9753cSRobert Watson error = priv_check(td, PRIV_NETINET_RAW);
820acd3428bSRobert Watson if (error)
8210ae76120SRobert Watson return (error);
82214ba8addSRobert Watson if (proto >= IPPROTO_MAX || proto < 0)
8234d3ffc98SBill Fenner return EPROTONOSUPPORT;
8246a800098SYoshinobu Inoue error = soreserve(so, rip_sendspace, rip_recvspace);
82514ba8addSRobert Watson if (error)
8260ae76120SRobert Watson return (error);
827603724d3SBjoern A. Zeeb error = in_pcballoc(so, &V_ripcbinfo);
828db0ac6deSCy Schubert if (error)
8290ae76120SRobert Watson return (error);
830df8bae1dSRodney W. Grimes inp = (struct inpcb *)so->so_pcb;
831ca98b82cSDavid Greenman inp->inp_ip_p = proto;
832603724d3SBjoern A. Zeeb inp->inp_ip_ttl = V_ip_defttl;
833db0ac6deSCy Schubert INP_HASH_WLOCK(&V_ripcbinfo);
8349ed324c9SAlexander Motin rip_inshash(inp);
835db0ac6deSCy Schubert INP_HASH_WUNLOCK(&V_ripcbinfo);
8368501a69cSRobert Watson INP_WUNLOCK(inp);
8370ae76120SRobert Watson return (0);
838df8bae1dSRodney W. Grimes }
839117bcae7SGarrett Wollman
84050d7c061SSam Leffler static void
rip_detach(struct socket * so)841a152f8a3SRobert Watson rip_detach(struct socket *so)
84250d7c061SSam Leffler {
843a152f8a3SRobert Watson struct inpcb *inp;
8443ca1570cSRobert Watson
845a152f8a3SRobert Watson inp = sotoinpcb(so);
846a152f8a3SRobert Watson KASSERT(inp != NULL, ("rip_detach: inp == NULL"));
847a152f8a3SRobert Watson KASSERT(inp->inp_faddr.s_addr == INADDR_ANY,
848a152f8a3SRobert Watson ("rip_detach: not closed"));
84950d7c061SSam Leffler
85077223d98SWojciech Macek /* Disable mrouter first */
8519ce46cbcSWojciech Macek if (so == V_ip_mrouter && ip_mrouter_done)
85277223d98SWojciech Macek ip_mrouter_done();
8539ce46cbcSWojciech Macek
8548501a69cSRobert Watson INP_WLOCK(inp);
855db0ac6deSCy Schubert INP_HASH_WLOCK(&V_ripcbinfo);
8569ed324c9SAlexander Motin rip_delhash(inp);
857db0ac6deSCy Schubert INP_HASH_WUNLOCK(&V_ripcbinfo);
8589ce46cbcSWojciech Macek
85950d7c061SSam Leffler if (ip_rsvp_force_done)
86050d7c061SSam Leffler ip_rsvp_force_done(so);
861603724d3SBjoern A. Zeeb if (so == V_ip_rsvpd)
86250d7c061SSam Leffler ip_rsvp_done();
86314ba8addSRobert Watson in_pcbfree(inp);
86450d7c061SSam Leffler }
86550d7c061SSam Leffler
866bc725eafSRobert Watson static void
rip_dodisconnect(struct socket * so,struct inpcb * inp)867a152f8a3SRobert Watson rip_dodisconnect(struct socket *so, struct inpcb *inp)
868117bcae7SGarrett Wollman {
869fa046d87SRobert Watson struct inpcbinfo *pcbinfo;
87018f401c6SAlexander Motin
871fa046d87SRobert Watson pcbinfo = inp->inp_pcbinfo;
872fa046d87SRobert Watson INP_WLOCK(inp);
873db0ac6deSCy Schubert INP_HASH_WLOCK(pcbinfo);
8749ed324c9SAlexander Motin rip_delhash(inp);
875a152f8a3SRobert Watson inp->inp_faddr.s_addr = INADDR_ANY;
8769ed324c9SAlexander Motin rip_inshash(inp);
877db0ac6deSCy Schubert INP_HASH_WUNLOCK(pcbinfo);
878a152f8a3SRobert Watson SOCK_LOCK(so);
879a152f8a3SRobert Watson so->so_state &= ~SS_ISCONNECTED;
880a152f8a3SRobert Watson SOCK_UNLOCK(so);
881fa046d87SRobert Watson INP_WUNLOCK(inp);
882117bcae7SGarrett Wollman }
883df8bae1dSRodney W. Grimes
884ac45e92fSRobert Watson static void
rip_abort(struct socket * so)885117bcae7SGarrett Wollman rip_abort(struct socket *so)
886df8bae1dSRodney W. Grimes {
88750d7c061SSam Leffler struct inpcb *inp;
88850d7c061SSam Leffler
88950d7c061SSam Leffler inp = sotoinpcb(so);
89014ba8addSRobert Watson KASSERT(inp != NULL, ("rip_abort: inp == NULL"));
891a152f8a3SRobert Watson
892a152f8a3SRobert Watson rip_dodisconnect(so, inp);
893a152f8a3SRobert Watson }
894a152f8a3SRobert Watson
895a152f8a3SRobert Watson static void
rip_close(struct socket * so)896a152f8a3SRobert Watson rip_close(struct socket *so)
897a152f8a3SRobert Watson {
898a152f8a3SRobert Watson struct inpcb *inp;
899a152f8a3SRobert Watson
900a152f8a3SRobert Watson inp = sotoinpcb(so);
901a152f8a3SRobert Watson KASSERT(inp != NULL, ("rip_close: inp == NULL"));
902a152f8a3SRobert Watson
903a152f8a3SRobert Watson rip_dodisconnect(so, inp);
904117bcae7SGarrett Wollman }
905117bcae7SGarrett Wollman
906117bcae7SGarrett Wollman static int
rip_disconnect(struct socket * so)907117bcae7SGarrett Wollman rip_disconnect(struct socket *so)
908117bcae7SGarrett Wollman {
909eb16472fSMaxim Konovalov struct inpcb *inp;
910eb16472fSMaxim Konovalov
9114cc20ab1SSeigo Tanimura if ((so->so_state & SS_ISCONNECTED) == 0)
9120ae76120SRobert Watson return (ENOTCONN);
913eb16472fSMaxim Konovalov
914eb16472fSMaxim Konovalov inp = sotoinpcb(so);
915eb16472fSMaxim Konovalov KASSERT(inp != NULL, ("rip_disconnect: inp == NULL"));
9160ae76120SRobert Watson
917a152f8a3SRobert Watson rip_dodisconnect(so, inp);
91814ba8addSRobert Watson return (0);
919117bcae7SGarrett Wollman }
920117bcae7SGarrett Wollman
921117bcae7SGarrett Wollman static int
rip_bind(struct socket * so,struct sockaddr * nam,struct thread * td)922b40ce416SJulian Elischer rip_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
923117bcae7SGarrett Wollman {
92457bf258eSGarrett Wollman struct sockaddr_in *addr = (struct sockaddr_in *)nam;
92550d7c061SSam Leffler struct inpcb *inp;
926b89e82ddSJamie Gritton int error;
927df8bae1dSRodney W. Grimes
928f161d294SMark Johnston if (nam->sa_family != AF_INET)
929f161d294SMark Johnston return (EAFNOSUPPORT);
93057bf258eSGarrett Wollman if (nam->sa_len != sizeof(*addr))
9310ae76120SRobert Watson return (EINVAL);
932117bcae7SGarrett Wollman
933b89e82ddSJamie Gritton error = prison_check_ip4(td->td_ucred, &addr->sin_addr);
934b89e82ddSJamie Gritton if (error != 0)
935b89e82ddSJamie Gritton return (error);
9365a59cefcSBosko Milekic
937f44270e7SPawel Jakub Dawidek inp = sotoinpcb(so);
938f44270e7SPawel Jakub Dawidek KASSERT(inp != NULL, ("rip_bind: inp == NULL"));
939f44270e7SPawel Jakub Dawidek
9404f6c66ccSMatt Macy if (CK_STAILQ_EMPTY(&V_ifnet) ||
94150d7c061SSam Leffler (addr->sin_family != AF_INET && addr->sin_family != AF_IMPLINK) ||
942032dcc76SLuigi Rizzo (addr->sin_addr.s_addr &&
943f44270e7SPawel Jakub Dawidek (inp->inp_flags & INP_BINDANY) == 0 &&
9448896f83aSRobert Watson ifa_ifwithaddr_check((struct sockaddr *)addr) == 0))
9450ae76120SRobert Watson return (EADDRNOTAVAIL);
94650d7c061SSam Leffler
9478501a69cSRobert Watson INP_WLOCK(inp);
948db0ac6deSCy Schubert INP_HASH_WLOCK(&V_ripcbinfo);
9499ed324c9SAlexander Motin rip_delhash(inp);
950df8bae1dSRodney W. Grimes inp->inp_laddr = addr->sin_addr;
9519ed324c9SAlexander Motin rip_inshash(inp);
952db0ac6deSCy Schubert INP_HASH_WUNLOCK(&V_ripcbinfo);
9538501a69cSRobert Watson INP_WUNLOCK(inp);
9540ae76120SRobert Watson return (0);
955df8bae1dSRodney W. Grimes }
956117bcae7SGarrett Wollman
957117bcae7SGarrett Wollman static int
rip_connect(struct socket * so,struct sockaddr * nam,struct thread * td)958b40ce416SJulian Elischer rip_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
959df8bae1dSRodney W. Grimes {
96057bf258eSGarrett Wollman struct sockaddr_in *addr = (struct sockaddr_in *)nam;
96150d7c061SSam Leffler struct inpcb *inp;
962df8bae1dSRodney W. Grimes
96357bf258eSGarrett Wollman if (nam->sa_len != sizeof(*addr))
9640ae76120SRobert Watson return (EINVAL);
9654f6c66ccSMatt Macy if (CK_STAILQ_EMPTY(&V_ifnet))
9660ae76120SRobert Watson return (EADDRNOTAVAIL);
96750d7c061SSam Leffler if (addr->sin_family != AF_INET && addr->sin_family != AF_IMPLINK)
9680ae76120SRobert Watson return (EAFNOSUPPORT);
96950d7c061SSam Leffler
97050d7c061SSam Leffler inp = sotoinpcb(so);
97114ba8addSRobert Watson KASSERT(inp != NULL, ("rip_connect: inp == NULL"));
9720ae76120SRobert Watson
9738501a69cSRobert Watson INP_WLOCK(inp);
974db0ac6deSCy Schubert INP_HASH_WLOCK(&V_ripcbinfo);
9759ed324c9SAlexander Motin rip_delhash(inp);
976df8bae1dSRodney W. Grimes inp->inp_faddr = addr->sin_addr;
9779ed324c9SAlexander Motin rip_inshash(inp);
978db0ac6deSCy Schubert INP_HASH_WUNLOCK(&V_ripcbinfo);
979df8bae1dSRodney W. Grimes soisconnected(so);
9808501a69cSRobert Watson INP_WUNLOCK(inp);
9810ae76120SRobert Watson return (0);
982df8bae1dSRodney W. Grimes }
983df8bae1dSRodney W. Grimes
984117bcae7SGarrett Wollman static int
rip_shutdown(struct socket * so,enum shutdown_how how)9855bba2728SGleb Smirnoff rip_shutdown(struct socket *so, enum shutdown_how how)
986df8bae1dSRodney W. Grimes {
98750d7c061SSam Leffler
9885bba2728SGleb Smirnoff SOCK_LOCK(so);
9895bba2728SGleb Smirnoff if (!(so->so_state & SS_ISCONNECTED)) {
9905bba2728SGleb Smirnoff SOCK_UNLOCK(so);
9915bba2728SGleb Smirnoff return (ENOTCONN);
9925bba2728SGleb Smirnoff }
9935bba2728SGleb Smirnoff SOCK_UNLOCK(so);
9940ae76120SRobert Watson
9955bba2728SGleb Smirnoff switch (how) {
9965bba2728SGleb Smirnoff case SHUT_RD:
997*ce69e373SGleb Smirnoff sorflush(so);
9985bba2728SGleb Smirnoff break;
9995bba2728SGleb Smirnoff case SHUT_RDWR:
1000*ce69e373SGleb Smirnoff sorflush(so);
10015bba2728SGleb Smirnoff /* FALLTHROUGH */
10025bba2728SGleb Smirnoff case SHUT_WR:
1003117bcae7SGarrett Wollman socantsendmore(so);
10045bba2728SGleb Smirnoff }
10055bba2728SGleb Smirnoff
10060ae76120SRobert Watson return (0);
1007117bcae7SGarrett Wollman }
100800c081e9SBjoern A. Zeeb #endif /* INET */
1009df8bae1dSRodney W. Grimes
101098271db4SGarrett Wollman static int
rip_pcblist(SYSCTL_HANDLER_ARGS)101182d9ae4eSPoul-Henning Kamp rip_pcblist(SYSCTL_HANDLER_ARGS)
101298271db4SGarrett Wollman {
1013db0ac6deSCy Schubert struct inpcb_iterator inpi = INP_ALL_ITERATOR(&V_ripcbinfo,
1014db0ac6deSCy Schubert INPLOOKUP_RLOCKPCB);
101598271db4SGarrett Wollman struct xinpgen xig;
1016032677ceSGleb Smirnoff struct inpcb *inp;
1017032677ceSGleb Smirnoff int error;
101898271db4SGarrett Wollman
1019032677ceSGleb Smirnoff if (req->newptr != 0)
1020032677ceSGleb Smirnoff return (EPERM);
1021032677ceSGleb Smirnoff
102298271db4SGarrett Wollman if (req->oldptr == 0) {
1023032677ceSGleb Smirnoff int n;
1024032677ceSGleb Smirnoff
1025603724d3SBjoern A. Zeeb n = V_ripcbinfo.ipi_count;
1026c007b96aSJohn Baldwin n += imax(n / 8, 10);
1027c007b96aSJohn Baldwin req->oldidx = 2 * (sizeof xig) + n * sizeof(struct xinpcb);
10280ae76120SRobert Watson return (0);
102998271db4SGarrett Wollman }
103098271db4SGarrett Wollman
1031032677ceSGleb Smirnoff if ((error = sysctl_wire_old_buffer(req, 0)) != 0)
1032032677ceSGleb Smirnoff return (error);
103398271db4SGarrett Wollman
103479db6fe7SMark Johnston bzero(&xig, sizeof(xig));
103598271db4SGarrett Wollman xig.xig_len = sizeof xig;
1036032677ceSGleb Smirnoff xig.xig_count = V_ripcbinfo.ipi_count;
1037032677ceSGleb Smirnoff xig.xig_gen = V_ripcbinfo.ipi_gencnt;
103898271db4SGarrett Wollman xig.xig_sogen = so_gencnt;
103998271db4SGarrett Wollman error = SYSCTL_OUT(req, &xig, sizeof xig);
104098271db4SGarrett Wollman if (error)
10410ae76120SRobert Watson return (error);
104298271db4SGarrett Wollman
1043db0ac6deSCy Schubert while ((inp = inp_next(&inpi)) != NULL) {
1044032677ceSGleb Smirnoff if (inp->inp_gencnt <= xig.xig_gen &&
1045032677ceSGleb Smirnoff cr_canseeinpcb(req->td->td_ucred, inp) == 0) {
104698271db4SGarrett Wollman struct xinpcb xi;
10473bb87a6cSKip Macy
1048cc65eb4eSGleb Smirnoff in_pcbtoxinpcb(inp, &xi);
1049266f97b5SCy Schubert error = SYSCTL_OUT(req, &xi, sizeof xi);
1050db0ac6deSCy Schubert if (error) {
1051266f97b5SCy Schubert INP_RUNLOCK(inp);
1052db0ac6deSCy Schubert break;
105398271db4SGarrett Wollman }
1054db0ac6deSCy Schubert }
1055db0ac6deSCy Schubert }
1056d0e157f6SBjoern A. Zeeb
105798271db4SGarrett Wollman if (!error) {
105898271db4SGarrett Wollman /*
10590ae76120SRobert Watson * Give the user an updated idea of our state. If the
10600ae76120SRobert Watson * generation differs from what we told her before, she knows
10610ae76120SRobert Watson * that something happened while we were processing this
10620ae76120SRobert Watson * request, and it might be necessary to retry.
106398271db4SGarrett Wollman */
1064603724d3SBjoern A. Zeeb xig.xig_gen = V_ripcbinfo.ipi_gencnt;
106598271db4SGarrett Wollman xig.xig_sogen = so_gencnt;
1066603724d3SBjoern A. Zeeb xig.xig_count = V_ripcbinfo.ipi_count;
106798271db4SGarrett Wollman error = SYSCTL_OUT(req, &xig, sizeof xig);
106898271db4SGarrett Wollman }
1069032677ceSGleb Smirnoff
10700ae76120SRobert Watson return (error);
107198271db4SGarrett Wollman }
107298271db4SGarrett Wollman
107379c3d51bSMatthew D Fleming SYSCTL_PROC(_net_inet_raw, OID_AUTO/*XXX*/, pcblist,
10747029da5cSPawel Biernacki CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
10757029da5cSPawel Biernacki rip_pcblist, "S,xinpcb",
10767029da5cSPawel Biernacki "List of active raw IP sockets");
107798271db4SGarrett Wollman
107800c081e9SBjoern A. Zeeb #ifdef INET
1079e7d02be1SGleb Smirnoff struct protosw rip_protosw = {
108061f7427fSGleb Smirnoff .pr_type = SOCK_RAW,
108161f7427fSGleb Smirnoff .pr_flags = PR_ATOMIC|PR_ADDR,
108261f7427fSGleb Smirnoff .pr_ctloutput = rip_ctloutput,
108361f7427fSGleb Smirnoff .pr_abort = rip_abort,
108461f7427fSGleb Smirnoff .pr_attach = rip_attach,
108561f7427fSGleb Smirnoff .pr_bind = rip_bind,
108661f7427fSGleb Smirnoff .pr_connect = rip_connect,
108761f7427fSGleb Smirnoff .pr_control = in_control,
108861f7427fSGleb Smirnoff .pr_detach = rip_detach,
108961f7427fSGleb Smirnoff .pr_disconnect = rip_disconnect,
109061f7427fSGleb Smirnoff .pr_peeraddr = in_getpeeraddr,
109161f7427fSGleb Smirnoff .pr_send = rip_send,
109261f7427fSGleb Smirnoff .pr_shutdown = rip_shutdown,
109361f7427fSGleb Smirnoff .pr_sockaddr = in_getsockaddr,
109461f7427fSGleb Smirnoff .pr_sosetlabel = in_pcbsosetlabel,
109561f7427fSGleb Smirnoff .pr_close = rip_close
1096117bcae7SGarrett Wollman };
109700c081e9SBjoern A. Zeeb #endif /* INET */
1098