1/*	$NetBSD: raw_ip.c,v 1.184 2022/11/04 09:00:58 ozaki-r Exp $	*/
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * Copyright (c) 1982, 1986, 1988, 1993
34 *	The Regents of the University of California.  All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 *    notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 *    notice, this list of conditions and the following disclaimer in the
43 *    documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the University nor the names of its contributors
45 *    may be used to endorse or promote products derived from this software
46 *    without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 *	@(#)raw_ip.c	8.7 (Berkeley) 5/15/95
61 */
62
63/*
64 * Raw interface to IP protocol.
65 */
66
67#include <sys/cdefs.h>
68__KERNEL_RCSID(0, "$NetBSD: raw_ip.c,v 1.184 2022/11/04 09:00:58 ozaki-r Exp $");
69
70#ifdef _KERNEL_OPT
71#include "opt_inet.h"
72#include "opt_ipsec.h"
73#include "opt_mrouting.h"
74#include "opt_net_mpsafe.h"
75#endif
76
77#include <sys/param.h>
78#include <sys/sysctl.h>
79#include <sys/mbuf.h>
80#include <sys/socket.h>
81#include <sys/protosw.h>
82#include <sys/socketvar.h>
83#include <sys/errno.h>
84#include <sys/systm.h>
85#include <sys/proc.h>
86#include <sys/kauth.h>
87
88#include <net/if.h>
89
90#include <netinet/in.h>
91#include <netinet/in_systm.h>
92#include <netinet/ip.h>
93#include <netinet/ip_var.h>
94#include <netinet/ip_private.h>
95#include <netinet/ip_mroute.h>
96#include <netinet/ip_icmp.h>
97#include <netinet/in_pcb.h>
98#include <netinet/in_proto.h>
99#include <netinet/in_var.h>
100
101#ifdef IPSEC
102#include <netipsec/ipsec.h>
103#endif
104
105struct inpcbtable rawcbtable;
106
107int	 rip_pcbnotify(struct inpcbtable *, struct in_addr,
108    struct in_addr, int, int, void (*)(struct inpcb *, int));
109static int	 rip_connect_pcb(struct inpcb *, struct sockaddr_in *);
110static void	 rip_disconnect1(struct inpcb *);
111
112static void sysctl_net_inet_raw_setup(struct sysctllog **);
113
114/*
115 * Nominal space allocated to a raw ip socket.
116 */
117#define	RIPSNDQ		8192
118#define	RIPRCVQ		8192
119
120static u_long		rip_sendspace = RIPSNDQ;
121static u_long		rip_recvspace = RIPRCVQ;
122
123/*
124 * Raw interface to IP protocol.
125 */
126
127/*
128 * Initialize raw connection block q.
129 */
130void
131rip_init(void)
132{
133
134	sysctl_net_inet_raw_setup(NULL);
135	inpcb_init(&rawcbtable, 1, 1);
136}
137
138static void
139rip_sbappendaddr(struct inpcb *last, struct ip *ip, const struct sockaddr *sa,
140    int hlen, struct mbuf *n)
141{
142	struct mbuf *opts = NULL;
143
144	if (last->inp_flags & INP_NOHEADER)
145		m_adj(n, hlen);
146	if (last->inp_flags & INP_CONTROLOPTS ||
147	    SOOPT_TIMESTAMP(last->inp_socket->so_options))
148		ip_savecontrol(last, &opts, ip, n);
149	if (sbappendaddr(&last->inp_socket->so_rcv, sa, n, opts) == 0) {
150		soroverflow(last->inp_socket);
151		m_freem(n);
152		if (opts)
153			m_freem(opts);
154	} else {
155		sorwakeup(last->inp_socket);
156	}
157}
158
159/*
160 * Setup generic address and protocol structures
161 * for raw_input routine, then pass them along with
162 * mbuf chain.
163 */
164void
165rip_input(struct mbuf *m, int off, int proto)
166{
167	struct ip *ip = mtod(m, struct ip *);
168	struct inpcb *inp;
169	struct inpcb *last = NULL;
170	struct mbuf *n;
171	struct sockaddr_in ripsrc;
172	int hlen;
173
174	sockaddr_in_init(&ripsrc, &ip->ip_src, 0);
175
176	/*
177	 * XXX Compatibility: programs using raw IP expect ip_len
178	 * XXX to have the header length subtracted, and in host order.
179	 * XXX ip_off is also expected to be host order.
180	 */
181	hlen = ip->ip_hl << 2;
182	ip->ip_len = ntohs(ip->ip_len) - hlen;
183	NTOHS(ip->ip_off);
184
185	TAILQ_FOREACH(inp, &rawcbtable.inpt_queue, inp_queue) {
186		if (inp->inp_af != AF_INET)
187			continue;
188		if (in4p_ip(inp).ip_p && in4p_ip(inp).ip_p != proto)
189			continue;
190		if (!in_nullhost(in4p_laddr(inp)) &&
191		    !in_hosteq(in4p_laddr(inp), ip->ip_dst))
192			continue;
193		if (!in_nullhost(in4p_faddr(inp)) &&
194		    !in_hosteq(in4p_faddr(inp), ip->ip_src))
195			continue;
196
197		if (last == NULL) {
198			;
199		}
200#if defined(IPSEC)
201		else if (ipsec_used && ipsec_in_reject(m, last)) {
202			/* do not inject data into pcb */
203		}
204#endif
205		else if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) {
206			rip_sbappendaddr(last, ip, sintosa(&ripsrc), hlen, n);
207		}
208
209		last = inp;
210	}
211
212#if defined(IPSEC)
213	if (ipsec_used && last != NULL && ipsec_in_reject(m, last)) {
214		m_freem(m);
215		IP_STATDEC(IP_STAT_DELIVERED);
216		/* do not inject data into pcb */
217	} else
218#endif
219	if (last != NULL) {
220		rip_sbappendaddr(last, ip, sintosa(&ripsrc), hlen, m);
221	} else if (inetsw[ip_protox[ip->ip_p]].pr_input == rip_input) {
222		uint64_t *ips;
223
224		icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL,
225		    0, 0);
226		ips = IP_STAT_GETREF();
227		ips[IP_STAT_NOPROTO]++;
228		ips[IP_STAT_DELIVERED]--;
229		IP_STAT_PUTREF();
230	} else {
231		m_freem(m);
232	}
233
234	return;
235}
236
237int
238rip_pcbnotify(struct inpcbtable *table,
239    struct in_addr faddr, struct in_addr laddr, int proto, int errno,
240    void (*notify)(struct inpcb *, int))
241{
242	struct inpcb *inp;
243	int nmatch;
244
245	nmatch = 0;
246	TAILQ_FOREACH(inp, &table->inpt_queue, inp_queue) {
247		if (inp->inp_af != AF_INET)
248			continue;
249		if (in4p_ip(inp).ip_p && in4p_ip(inp).ip_p != proto)
250			continue;
251		if (in_hosteq(in4p_faddr(inp), faddr) &&
252		    in_hosteq(in4p_laddr(inp), laddr)) {
253			(*notify)(inp, errno);
254			nmatch++;
255		}
256	}
257
258	return nmatch;
259}
260
261void *
262rip_ctlinput(int cmd, const struct sockaddr *sa, void *v)
263{
264	struct ip *ip = v;
265	void (*notify)(struct inpcb *, int) = inpcb_rtchange;
266	int errno;
267
268	if (sa->sa_family != AF_INET ||
269	    sa->sa_len != sizeof(struct sockaddr_in))
270		return NULL;
271	if ((unsigned)cmd >= PRC_NCMDS)
272		return NULL;
273	errno = inetctlerrmap[cmd];
274	if (PRC_IS_REDIRECT(cmd))
275		notify = inpcb_rtchange, ip = 0;
276	else if (cmd == PRC_HOSTDEAD)
277		ip = 0;
278	else if (errno == 0)
279		return NULL;
280	if (ip) {
281		rip_pcbnotify(&rawcbtable, satocsin(sa)->sin_addr,
282		    ip->ip_src, ip->ip_p, errno, notify);
283
284		/* XXX mapped address case */
285	} else
286		inpcb_notifyall(&rawcbtable, satocsin(sa)->sin_addr, errno,
287		    notify);
288	return NULL;
289}
290
291/*
292 * Generate IP header and pass packet to ip_output.
293 * Tack on options user may have setup with control call.
294 */
295int
296rip_output(struct mbuf *m, struct inpcb *inp, struct mbuf *control,
297    struct lwp *l)
298{
299	struct ip *ip;
300	struct mbuf *opts;
301	struct ip_pktopts pktopts;
302	kauth_cred_t cred;
303	int error, flags;
304
305	flags = (inp->inp_socket->so_options & SO_DONTROUTE) |
306	    IP_ALLOWBROADCAST | IP_RETURNMTU;
307
308	if (l == NULL)
309		cred = NULL;
310	else
311		cred = l->l_cred;
312
313	/* Setup IP outgoing packet options */
314	memset(&pktopts, 0, sizeof(pktopts));
315	error = ip_setpktopts(control, &pktopts, &flags, inp, cred);
316	if (control != NULL)
317		m_freem(control);
318	if (error != 0)
319		goto release;
320
321	/*
322	 * If the user handed us a complete IP packet, use it.
323	 * Otherwise, allocate an mbuf for a header and fill it in.
324	 */
325	if ((inp->inp_flags & INP_HDRINCL) == 0) {
326		if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) {
327			error = EMSGSIZE;
328			goto release;
329		}
330		M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
331		if (!m) {
332			error = ENOBUFS;
333			goto release;
334		}
335		ip = mtod(m, struct ip *);
336		ip->ip_tos = 0;
337		ip->ip_off = htons(0);
338		ip->ip_p = in4p_ip(inp).ip_p;
339		ip->ip_len = htons(m->m_pkthdr.len);
340		ip->ip_src = pktopts.ippo_laddr.sin_addr;
341		ip->ip_dst = in4p_faddr(inp);
342		ip->ip_ttl = MAXTTL;
343		opts = inp->inp_options;
344	} else {
345		if (m->m_pkthdr.len > IP_MAXPACKET) {
346			error = EMSGSIZE;
347			goto release;
348		}
349		if (m->m_pkthdr.len < sizeof(struct ip)) {
350			error = EINVAL;
351			goto release;
352		}
353		ip = mtod(m, struct ip *);
354
355		/*
356		 * If the mbuf is read-only, we need to allocate
357		 * a new mbuf for the header, since we need to
358		 * modify the header.
359		 */
360		if (M_READONLY(m)) {
361			int hlen = ip->ip_hl << 2;
362
363			m = m_copyup(m, hlen, (max_linkhdr + 3) & ~3);
364			if (m == NULL) {
365				error = ENOMEM;
366				goto release;
367			}
368			ip = mtod(m, struct ip *);
369		}
370
371		/* XXX userland passes ip_len and ip_off in host order */
372		if (m->m_pkthdr.len != ip->ip_len) {
373			error = EINVAL;
374			goto release;
375		}
376		HTONS(ip->ip_len);
377		HTONS(ip->ip_off);
378
379		if (ip->ip_id != 0 || m->m_pkthdr.len < IP_MINFRAGSIZE)
380			flags |= IP_NOIPNEWID;
381		opts = NULL;
382
383		/* Prevent ip_output from overwriting header fields. */
384		flags |= IP_RAWOUTPUT;
385
386		IP_STATINC(IP_STAT_RAWOUT);
387	}
388
389	/*
390	 * IP output.  Note: if IP_RETURNMTU flag is set, the MTU size
391	 * will be stored in inp_errormtu.
392	 */
393	return ip_output(m, opts, &inp->inp_route, flags, pktopts.ippo_imo,
394	    inp);
395
396 release:
397	if (m != NULL)
398		m_freem(m);
399	return error;
400}
401
402/*
403 * Raw IP socket option processing.
404 */
405int
406rip_ctloutput(int op, struct socket *so, struct sockopt *sopt)
407{
408	struct inpcb *inp = sotoinpcb(so);
409	int error = 0;
410	int optval;
411
412	if (sopt->sopt_level == SOL_SOCKET && sopt->sopt_name == SO_NOHEADER) {
413		if (op == PRCO_GETOPT) {
414			optval = (inp->inp_flags & INP_NOHEADER) ? 1 : 0;
415			error = sockopt_set(sopt, &optval, sizeof(optval));
416		} else if (op == PRCO_SETOPT) {
417			error = sockopt_getint(sopt, &optval);
418			if (error)
419				goto out;
420			if (optval) {
421				inp->inp_flags &= ~INP_HDRINCL;
422				inp->inp_flags |= INP_NOHEADER;
423			} else
424				inp->inp_flags &= ~INP_NOHEADER;
425		}
426		goto out;
427	} else if (sopt->sopt_level != IPPROTO_IP)
428		return ip_ctloutput(op, so, sopt);
429
430	switch (op) {
431
432	case PRCO_SETOPT:
433		switch (sopt->sopt_name) {
434		case IP_HDRINCL:
435			error = sockopt_getint(sopt, &optval);
436			if (error)
437				break;
438			if (optval)
439				inp->inp_flags |= INP_HDRINCL;
440			else
441				inp->inp_flags &= ~INP_HDRINCL;
442			break;
443
444#ifdef MROUTING
445		case MRT_INIT:
446		case MRT_DONE:
447		case MRT_ADD_VIF:
448		case MRT_DEL_VIF:
449		case MRT_ADD_MFC:
450		case MRT_DEL_MFC:
451		case MRT_ASSERT:
452		case MRT_API_CONFIG:
453		case MRT_ADD_BW_UPCALL:
454		case MRT_DEL_BW_UPCALL:
455			error = ip_mrouter_set(so, sopt);
456			break;
457#endif
458
459		default:
460			error = ip_ctloutput(op, so, sopt);
461			break;
462		}
463		break;
464
465	case PRCO_GETOPT:
466		switch (sopt->sopt_name) {
467		case IP_HDRINCL:
468			optval = inp->inp_flags & INP_HDRINCL;
469			error = sockopt_set(sopt, &optval, sizeof(optval));
470			break;
471
472#ifdef MROUTING
473		case MRT_VERSION:
474		case MRT_ASSERT:
475		case MRT_API_SUPPORT:
476		case MRT_API_CONFIG:
477			error = ip_mrouter_get(so, sopt);
478			break;
479#endif
480
481		default:
482			error = ip_ctloutput(op, so, sopt);
483			break;
484		}
485		break;
486	}
487 out:
488	return error;
489}
490
491int
492rip_connect_pcb(struct inpcb *inp, struct sockaddr_in *addr)
493{
494
495	if (IFNET_READER_EMPTY())
496		return (EADDRNOTAVAIL);
497	if (addr->sin_family != AF_INET)
498		return (EAFNOSUPPORT);
499	if (addr->sin_len != sizeof(*addr))
500		return EINVAL;
501	in4p_faddr(inp) = addr->sin_addr;
502	return (0);
503}
504
505static void
506rip_disconnect1(struct inpcb *inp)
507{
508
509	in4p_faddr(inp) = zeroin_addr;
510}
511
512static int
513rip_attach(struct socket *so, int proto)
514{
515	struct inpcb *inp;
516	int error;
517
518	KASSERT(sotoinpcb(so) == NULL);
519	sosetlock(so);
520
521	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
522		error = soreserve(so, rip_sendspace, rip_recvspace);
523		if (error) {
524			return error;
525		}
526	}
527
528	error = inpcb_create(so, &rawcbtable);
529	if (error) {
530		return error;
531	}
532	inp = sotoinpcb(so);
533	in4p_ip(inp).ip_p = proto;
534	KASSERT(solocked(so));
535
536	return 0;
537}
538
539static void
540rip_detach(struct socket *so)
541{
542	struct inpcb *inp;
543
544	KASSERT(solocked(so));
545	inp = sotoinpcb(so);
546	KASSERT(inp != NULL);
547
548#ifdef MROUTING
549	extern struct socket *ip_mrouter;
550	if (so == ip_mrouter) {
551		ip_mrouter_done();
552	}
553#endif
554	inpcb_destroy(inp);
555}
556
557static int
558rip_accept(struct socket *so, struct sockaddr *nam)
559{
560	KASSERT(solocked(so));
561
562	panic("rip_accept");
563
564	return EOPNOTSUPP;
565}
566
567static int
568rip_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
569{
570	struct inpcb *inp = sotoinpcb(so);
571	struct sockaddr_in *addr = (struct sockaddr_in *)nam;
572	int error = 0;
573	int s, ss;
574	struct ifaddr *ifa;
575
576	KASSERT(solocked(so));
577	KASSERT(inp != NULL);
578	KASSERT(nam != NULL);
579
580	if (addr->sin_len != sizeof(*addr))
581		return EINVAL;
582
583	s = splsoftnet();
584	if (IFNET_READER_EMPTY()) {
585		error = EADDRNOTAVAIL;
586		goto release;
587	}
588	if (addr->sin_family != AF_INET) {
589		error = EAFNOSUPPORT;
590		goto release;
591	}
592	ss = pserialize_read_enter();
593	if ((ifa = ifa_ifwithaddr(sintosa(addr))) == NULL &&
594	    (inp->inp_flags & INP_BINDANY) == 0 &&
595	    !in_nullhost(addr->sin_addr))
596	{
597		pserialize_read_exit(ss);
598		error = EADDRNOTAVAIL;
599		goto release;
600	}
601        if (ifa && (ifatoia(ifa))->ia4_flags & IN6_IFF_DUPLICATED) {
602		pserialize_read_exit(ss);
603		error = EADDRNOTAVAIL;
604		goto release;
605	}
606	pserialize_read_exit(ss);
607
608	in4p_laddr(inp) = addr->sin_addr;
609
610release:
611	splx(s);
612	return error;
613}
614
615static int
616rip_listen(struct socket *so, struct lwp *l)
617{
618	KASSERT(solocked(so));
619
620	return EOPNOTSUPP;
621}
622
623static int
624rip_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
625{
626	struct inpcb *inp = sotoinpcb(so);
627	int error = 0;
628	int s;
629
630	KASSERT(solocked(so));
631	KASSERT(inp != NULL);
632	KASSERT(nam != NULL);
633
634	s = splsoftnet();
635	error = rip_connect_pcb(inp, (struct sockaddr_in *)nam);
636	if (! error)
637		soisconnected(so);
638	splx(s);
639
640	return error;
641}
642
643static int
644rip_connect2(struct socket *so, struct socket *so2)
645{
646	KASSERT(solocked(so));
647
648	return EOPNOTSUPP;
649}
650
651static int
652rip_disconnect(struct socket *so)
653{
654	struct inpcb *inp = sotoinpcb(so);
655	int s;
656
657	KASSERT(solocked(so));
658	KASSERT(inp != NULL);
659
660	s = splsoftnet();
661	soisdisconnected(so);
662	rip_disconnect1(inp);
663	splx(s);
664
665	return 0;
666}
667
668static int
669rip_shutdown(struct socket *so)
670{
671	int s;
672
673	KASSERT(solocked(so));
674
675	/*
676	 * Mark the connection as being incapable of further input.
677	 */
678	s = splsoftnet();
679	socantsendmore(so);
680	splx(s);
681
682	return 0;
683}
684
685static int
686rip_abort(struct socket *so)
687{
688	KASSERT(solocked(so));
689
690	panic("rip_abort");
691
692	return EOPNOTSUPP;
693}
694
695static int
696rip_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
697{
698	return in_control(so, cmd, nam, ifp);
699}
700
701static int
702rip_stat(struct socket *so, struct stat *ub)
703{
704	KASSERT(solocked(so));
705
706	/* stat: don't bother with a blocksize. */
707	return 0;
708}
709
710static int
711rip_peeraddr(struct socket *so, struct sockaddr *nam)
712{
713	int s;
714
715	KASSERT(solocked(so));
716	KASSERT(sotoinpcb(so) != NULL);
717	KASSERT(nam != NULL);
718
719	s = splsoftnet();
720	inpcb_fetch_peeraddr(sotoinpcb(so), (struct sockaddr_in *)nam);
721	splx(s);
722
723	return 0;
724}
725
726static int
727rip_sockaddr(struct socket *so, struct sockaddr *nam)
728{
729	int s;
730
731	KASSERT(solocked(so));
732	KASSERT(sotoinpcb(so) != NULL);
733	KASSERT(nam != NULL);
734
735	s = splsoftnet();
736	inpcb_fetch_sockaddr(sotoinpcb(so), (struct sockaddr_in *)nam);
737	splx(s);
738
739	return 0;
740}
741
742static int
743rip_rcvd(struct socket *so, int flags, struct lwp *l)
744{
745	KASSERT(solocked(so));
746
747	return EOPNOTSUPP;
748}
749
750static int
751rip_recvoob(struct socket *so, struct mbuf *m, int flags)
752{
753	KASSERT(solocked(so));
754
755	return EOPNOTSUPP;
756}
757
758static int
759rip_send(struct socket *so, struct mbuf *m, struct sockaddr *nam,
760    struct mbuf *control, struct lwp *l)
761{
762	struct inpcb *inp = sotoinpcb(so);
763	int error = 0;
764	int s;
765
766	KASSERT(solocked(so));
767	KASSERT(inp != NULL);
768	KASSERT(m != NULL);
769
770	/*
771	 * Ship a packet out.  The appropriate raw output
772	 * routine handles any massaging necessary.
773	 */
774	s = splsoftnet();
775	if (nam) {
776		if ((so->so_state & SS_ISCONNECTED) != 0) {
777			error = EISCONN;
778			goto die;
779		}
780		error = rip_connect_pcb(inp, (struct sockaddr_in *)nam);
781		if (error)
782			goto die;
783	} else {
784		if ((so->so_state & SS_ISCONNECTED) == 0) {
785			error = ENOTCONN;
786			goto die;
787		}
788	}
789	error = rip_output(m, inp, control, l);
790	m = NULL;
791	control = NULL;
792	if (nam)
793		rip_disconnect1(inp);
794 die:
795	if (m != NULL)
796		m_freem(m);
797	if (control != NULL)
798		m_freem(control);
799
800	splx(s);
801	return error;
802}
803
804static int
805rip_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
806{
807	KASSERT(solocked(so));
808
809	m_freem(m);
810	m_freem(control);
811
812	return EOPNOTSUPP;
813}
814
815static int
816rip_purgeif(struct socket *so, struct ifnet *ifp)
817{
818	int s;
819
820	s = splsoftnet();
821	mutex_enter(softnet_lock);
822	inpcb_purgeif0(&rawcbtable, ifp);
823#ifdef NET_MPSAFE
824	mutex_exit(softnet_lock);
825#endif
826	in_purgeif(ifp);
827#ifdef NET_MPSAFE
828	mutex_enter(softnet_lock);
829#endif
830	inpcb_purgeif(&rawcbtable, ifp);
831	mutex_exit(softnet_lock);
832	splx(s);
833
834	return 0;
835}
836
837PR_WRAP_USRREQS(rip)
838#define	rip_attach	rip_attach_wrapper
839#define	rip_detach	rip_detach_wrapper
840#define	rip_accept	rip_accept_wrapper
841#define	rip_bind	rip_bind_wrapper
842#define	rip_listen	rip_listen_wrapper
843#define	rip_connect	rip_connect_wrapper
844#define	rip_connect2	rip_connect2_wrapper
845#define	rip_disconnect	rip_disconnect_wrapper
846#define	rip_shutdown	rip_shutdown_wrapper
847#define	rip_abort	rip_abort_wrapper
848#define	rip_ioctl	rip_ioctl_wrapper
849#define	rip_stat	rip_stat_wrapper
850#define	rip_peeraddr	rip_peeraddr_wrapper
851#define	rip_sockaddr	rip_sockaddr_wrapper
852#define	rip_rcvd	rip_rcvd_wrapper
853#define	rip_recvoob	rip_recvoob_wrapper
854#define	rip_send	rip_send_wrapper
855#define	rip_sendoob	rip_sendoob_wrapper
856#define	rip_purgeif	rip_purgeif_wrapper
857
858const struct pr_usrreqs rip_usrreqs = {
859	.pr_attach	= rip_attach,
860	.pr_detach	= rip_detach,
861	.pr_accept	= rip_accept,
862	.pr_bind	= rip_bind,
863	.pr_listen	= rip_listen,
864	.pr_connect	= rip_connect,
865	.pr_connect2	= rip_connect2,
866	.pr_disconnect	= rip_disconnect,
867	.pr_shutdown	= rip_shutdown,
868	.pr_abort	= rip_abort,
869	.pr_ioctl	= rip_ioctl,
870	.pr_stat	= rip_stat,
871	.pr_peeraddr	= rip_peeraddr,
872	.pr_sockaddr	= rip_sockaddr,
873	.pr_rcvd	= rip_rcvd,
874	.pr_recvoob	= rip_recvoob,
875	.pr_send	= rip_send,
876	.pr_sendoob	= rip_sendoob,
877	.pr_purgeif	= rip_purgeif,
878};
879
880static void
881sysctl_net_inet_raw_setup(struct sysctllog **clog)
882{
883
884	sysctl_createv(clog, 0, NULL, NULL,
885		       CTLFLAG_PERMANENT,
886		       CTLTYPE_NODE, "inet", NULL,
887		       NULL, 0, NULL, 0,
888		       CTL_NET, PF_INET, CTL_EOL);
889	sysctl_createv(clog, 0, NULL, NULL,
890		       CTLFLAG_PERMANENT,
891		       CTLTYPE_NODE, "raw",
892		       SYSCTL_DESCR("Raw IPv4 settings"),
893		       NULL, 0, NULL, 0,
894		       CTL_NET, PF_INET, IPPROTO_RAW, CTL_EOL);
895
896	sysctl_createv(clog, 0, NULL, NULL,
897		       CTLFLAG_PERMANENT,
898		       CTLTYPE_STRUCT, "pcblist",
899		       SYSCTL_DESCR("Raw IPv4 control block list"),
900		       sysctl_inpcblist, 0, &rawcbtable, 0,
901		       CTL_NET, PF_INET, IPPROTO_RAW,
902		       CTL_CREATE, CTL_EOL);
903}
904