xref: /netbsd-src/sys/netinet/raw_ip.c (revision 481d3881954fd794ca5f2d880b68c53a5db8620e)
1 /*	$NetBSD: raw_ip.c,v 1.186 2024/07/05 04:31:54 rin 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.186 2024/07/05 04:31:54 rin 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 
105 struct inpcbtable rawcbtable;
106 
107 int	 rip_pcbnotify(struct inpcbtable *, struct in_addr,
108     struct in_addr, int, int, void (*)(struct inpcb *, int));
109 static int	 rip_connect_pcb(struct inpcb *, struct sockaddr_in *);
110 static void	 rip_disconnect1(struct inpcb *);
111 
112 static 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 
120 static u_long		rip_sendspace = RIPSNDQ;
121 static u_long		rip_recvspace = RIPRCVQ;
122 
123 /*
124  * Raw interface to IP protocol.
125  */
126 
127 /*
128  * Initialize raw connection block q.
129  */
130 void
rip_init(void)131 rip_init(void)
132 {
133 
134 	sysctl_net_inet_raw_setup(NULL);
135 	inpcb_init(&rawcbtable, 1, 1);
136 }
137 
138 static void
rip_sbappendaddr(struct inpcb * last,struct ip * ip,const struct sockaddr * sa,int hlen,struct mbuf * n)139 rip_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 		m_freem(opts);
153 	} else {
154 		sorwakeup(last->inp_socket);
155 	}
156 }
157 
158 /*
159  * Setup generic address and protocol structures
160  * for raw_input routine, then pass them along with
161  * mbuf chain.
162  */
163 void
rip_input(struct mbuf * m,int off,int proto)164 rip_input(struct mbuf *m, int off, int proto)
165 {
166 	struct ip *ip = mtod(m, struct ip *);
167 	struct inpcb *inp;
168 	struct inpcb *last = NULL;
169 	struct mbuf *n;
170 	struct sockaddr_in ripsrc;
171 	int hlen;
172 
173 	sockaddr_in_init(&ripsrc, &ip->ip_src, 0);
174 
175 	/*
176 	 * XXX Compatibility: programs using raw IP expect ip_len
177 	 * XXX to have the header length subtracted, and in host order.
178 	 * XXX ip_off is also expected to be host order.
179 	 */
180 	hlen = ip->ip_hl << 2;
181 	ip->ip_len = ntohs(ip->ip_len) - hlen;
182 	NTOHS(ip->ip_off);
183 
184 	TAILQ_FOREACH(inp, &rawcbtable.inpt_queue, inp_queue) {
185 		if (inp->inp_af != AF_INET)
186 			continue;
187 		if (in4p_ip(inp).ip_p && in4p_ip(inp).ip_p != proto)
188 			continue;
189 		if (!in_nullhost(in4p_laddr(inp)) &&
190 		    !in_hosteq(in4p_laddr(inp), ip->ip_dst))
191 			continue;
192 		if (!in_nullhost(in4p_faddr(inp)) &&
193 		    !in_hosteq(in4p_faddr(inp), ip->ip_src))
194 			continue;
195 
196 		if (last == NULL) {
197 			;
198 		}
199 #if defined(IPSEC)
200 		else if (ipsec_used && ipsec_in_reject(m, last)) {
201 			/* do not inject data into pcb */
202 		}
203 #endif
204 		else if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) {
205 			rip_sbappendaddr(last, ip, sintosa(&ripsrc), hlen, n);
206 		}
207 
208 		last = inp;
209 	}
210 
211 #if defined(IPSEC)
212 	if (ipsec_used && last != NULL && ipsec_in_reject(m, last)) {
213 		m_freem(m);
214 		IP_STATDEC(IP_STAT_DELIVERED);
215 		/* do not inject data into pcb */
216 	} else
217 #endif
218 	if (last != NULL) {
219 		rip_sbappendaddr(last, ip, sintosa(&ripsrc), hlen, m);
220 	} else if (inetsw[ip_protox[ip->ip_p]].pr_input == rip_input) {
221 		net_stat_ref_t ips;
222 
223 		icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL,
224 		    0, 0);
225 		ips = IP_STAT_GETREF();
226 		_NET_STATINC_REF(ips, IP_STAT_NOPROTO);
227 		_NET_STATDEC_REF(ips, IP_STAT_DELIVERED);
228 		IP_STAT_PUTREF();
229 	} else {
230 		m_freem(m);
231 	}
232 
233 	return;
234 }
235 
236 int
rip_pcbnotify(struct inpcbtable * table,struct in_addr faddr,struct in_addr laddr,int proto,int errno,void (* notify)(struct inpcb *,int))237 rip_pcbnotify(struct inpcbtable *table,
238     struct in_addr faddr, struct in_addr laddr, int proto, int errno,
239     void (*notify)(struct inpcb *, int))
240 {
241 	struct inpcb *inp;
242 	int nmatch;
243 
244 	nmatch = 0;
245 	TAILQ_FOREACH(inp, &table->inpt_queue, inp_queue) {
246 		if (inp->inp_af != AF_INET)
247 			continue;
248 		if (in4p_ip(inp).ip_p && in4p_ip(inp).ip_p != proto)
249 			continue;
250 		if (in_hosteq(in4p_faddr(inp), faddr) &&
251 		    in_hosteq(in4p_laddr(inp), laddr)) {
252 			(*notify)(inp, errno);
253 			nmatch++;
254 		}
255 	}
256 
257 	return nmatch;
258 }
259 
260 void *
rip_ctlinput(int cmd,const struct sockaddr * sa,void * v)261 rip_ctlinput(int cmd, const struct sockaddr *sa, void *v)
262 {
263 	struct ip *ip = v;
264 	void (*notify)(struct inpcb *, int) = inpcb_rtchange;
265 	int errno;
266 
267 	if (sa->sa_family != AF_INET ||
268 	    sa->sa_len != sizeof(struct sockaddr_in))
269 		return NULL;
270 	if ((unsigned)cmd >= PRC_NCMDS)
271 		return NULL;
272 	errno = inetctlerrmap[cmd];
273 	if (PRC_IS_REDIRECT(cmd))
274 		notify = inpcb_rtchange, ip = 0;
275 	else if (cmd == PRC_HOSTDEAD)
276 		ip = 0;
277 	else if (errno == 0)
278 		return NULL;
279 	if (ip) {
280 		rip_pcbnotify(&rawcbtable, satocsin(sa)->sin_addr,
281 		    ip->ip_src, ip->ip_p, errno, notify);
282 
283 		/* XXX mapped address case */
284 	} else
285 		inpcb_notifyall(&rawcbtable, satocsin(sa)->sin_addr, errno,
286 		    notify);
287 	return NULL;
288 }
289 
290 /*
291  * Generate IP header and pass packet to ip_output.
292  * Tack on options user may have setup with control call.
293  */
294 int
rip_output(struct mbuf * m,struct inpcb * inp,struct mbuf * control,struct lwp * l)295 rip_output(struct mbuf *m, struct inpcb *inp, struct mbuf *control,
296     struct lwp *l)
297 {
298 	struct ip *ip;
299 	struct mbuf *opts;
300 	struct ip_pktopts pktopts;
301 	kauth_cred_t cred;
302 	int error, flags;
303 
304 	flags = (inp->inp_socket->so_options & SO_DONTROUTE) |
305 	    IP_ALLOWBROADCAST | IP_RETURNMTU;
306 
307 	if (l == NULL)
308 		cred = NULL;
309 	else
310 		cred = l->l_cred;
311 
312 	/* Setup IP outgoing packet options */
313 	memset(&pktopts, 0, sizeof(pktopts));
314 	error = ip_setpktopts(control, &pktopts, &flags, inp, cred);
315 	m_freem(control);
316 	if (error != 0)
317 		goto release;
318 
319 	/*
320 	 * If the user handed us a complete IP packet, use it.
321 	 * Otherwise, allocate an mbuf for a header and fill it in.
322 	 */
323 	if ((inp->inp_flags & INP_HDRINCL) == 0) {
324 		if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) {
325 			error = EMSGSIZE;
326 			goto release;
327 		}
328 		M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
329 		if (!m) {
330 			error = ENOBUFS;
331 			goto release;
332 		}
333 		ip = mtod(m, struct ip *);
334 		ip->ip_tos = 0;
335 		ip->ip_off = htons(0);
336 		ip->ip_p = in4p_ip(inp).ip_p;
337 		ip->ip_len = htons(m->m_pkthdr.len);
338 		ip->ip_src = pktopts.ippo_laddr.sin_addr;
339 		ip->ip_dst = in4p_faddr(inp);
340 		ip->ip_ttl = MAXTTL;
341 		opts = inp->inp_options;
342 	} else {
343 		if (m->m_pkthdr.len > IP_MAXPACKET) {
344 			error = EMSGSIZE;
345 			goto release;
346 		}
347 		if (m->m_pkthdr.len < sizeof(struct ip)) {
348 			error = EINVAL;
349 			goto release;
350 		}
351 		ip = mtod(m, struct ip *);
352 
353 		/*
354 		 * If the mbuf is read-only, we need to allocate
355 		 * a new mbuf for the header, since we need to
356 		 * modify the header.
357 		 */
358 		if (M_READONLY(m)) {
359 			int hlen = ip->ip_hl << 2;
360 
361 			m = m_copyup(m, hlen, (max_linkhdr + 3) & ~3);
362 			if (m == NULL) {
363 				error = ENOMEM;
364 				goto release;
365 			}
366 			ip = mtod(m, struct ip *);
367 		}
368 
369 		/* XXX userland passes ip_len and ip_off in host order */
370 		if (m->m_pkthdr.len != ip->ip_len) {
371 			error = EINVAL;
372 			goto release;
373 		}
374 		HTONS(ip->ip_len);
375 		HTONS(ip->ip_off);
376 
377 		if (ip->ip_id != 0 || m->m_pkthdr.len < IP_MINFRAGSIZE)
378 			flags |= IP_NOIPNEWID;
379 		opts = NULL;
380 
381 		/* Prevent ip_output from overwriting header fields. */
382 		flags |= IP_RAWOUTPUT;
383 
384 		IP_STATINC(IP_STAT_RAWOUT);
385 	}
386 
387 	/*
388 	 * IP output.  Note: if IP_RETURNMTU flag is set, the MTU size
389 	 * will be stored in inp_errormtu.
390 	 */
391 	return ip_output(m, opts, &inp->inp_route, flags, pktopts.ippo_imo,
392 	    inp);
393 
394  release:
395 	m_freem(m);
396 	return error;
397 }
398 
399 /*
400  * Raw IP socket option processing.
401  */
402 int
rip_ctloutput(int op,struct socket * so,struct sockopt * sopt)403 rip_ctloutput(int op, struct socket *so, struct sockopt *sopt)
404 {
405 	struct inpcb *inp = sotoinpcb(so);
406 	int error = 0;
407 	int optval;
408 
409 	if (sopt->sopt_level == SOL_SOCKET && sopt->sopt_name == SO_NOHEADER) {
410 		if (op == PRCO_GETOPT) {
411 			optval = (inp->inp_flags & INP_NOHEADER) ? 1 : 0;
412 			error = sockopt_set(sopt, &optval, sizeof(optval));
413 		} else if (op == PRCO_SETOPT) {
414 			error = sockopt_getint(sopt, &optval);
415 			if (error)
416 				goto out;
417 			if (optval) {
418 				inp->inp_flags &= ~INP_HDRINCL;
419 				inp->inp_flags |= INP_NOHEADER;
420 			} else
421 				inp->inp_flags &= ~INP_NOHEADER;
422 		}
423 		goto out;
424 	} else if (sopt->sopt_level != IPPROTO_IP)
425 		return ip_ctloutput(op, so, sopt);
426 
427 	switch (op) {
428 
429 	case PRCO_SETOPT:
430 		switch (sopt->sopt_name) {
431 		case IP_HDRINCL:
432 			error = sockopt_getint(sopt, &optval);
433 			if (error)
434 				break;
435 			if (optval)
436 				inp->inp_flags |= INP_HDRINCL;
437 			else
438 				inp->inp_flags &= ~INP_HDRINCL;
439 			break;
440 
441 #ifdef MROUTING
442 		case MRT_INIT:
443 		case MRT_DONE:
444 		case MRT_ADD_VIF:
445 		case MRT_DEL_VIF:
446 		case MRT_ADD_MFC:
447 		case MRT_DEL_MFC:
448 		case MRT_ASSERT:
449 		case MRT_API_CONFIG:
450 		case MRT_ADD_BW_UPCALL:
451 		case MRT_DEL_BW_UPCALL:
452 			error = ip_mrouter_set(so, sopt);
453 			break;
454 #endif
455 
456 		default:
457 			error = ip_ctloutput(op, so, sopt);
458 			break;
459 		}
460 		break;
461 
462 	case PRCO_GETOPT:
463 		switch (sopt->sopt_name) {
464 		case IP_HDRINCL:
465 			optval = inp->inp_flags & INP_HDRINCL;
466 			error = sockopt_set(sopt, &optval, sizeof(optval));
467 			break;
468 
469 #ifdef MROUTING
470 		case MRT_VERSION:
471 		case MRT_ASSERT:
472 		case MRT_API_SUPPORT:
473 		case MRT_API_CONFIG:
474 			error = ip_mrouter_get(so, sopt);
475 			break;
476 #endif
477 
478 		default:
479 			error = ip_ctloutput(op, so, sopt);
480 			break;
481 		}
482 		break;
483 	}
484  out:
485 	return error;
486 }
487 
488 int
rip_connect_pcb(struct inpcb * inp,struct sockaddr_in * addr)489 rip_connect_pcb(struct inpcb *inp, struct sockaddr_in *addr)
490 {
491 
492 	if (IFNET_READER_EMPTY())
493 		return (EADDRNOTAVAIL);
494 	if (addr->sin_family != AF_INET)
495 		return (EAFNOSUPPORT);
496 	if (addr->sin_len != sizeof(*addr))
497 		return EINVAL;
498 	in4p_faddr(inp) = addr->sin_addr;
499 	return (0);
500 }
501 
502 static void
rip_disconnect1(struct inpcb * inp)503 rip_disconnect1(struct inpcb *inp)
504 {
505 
506 	in4p_faddr(inp) = zeroin_addr;
507 }
508 
509 static int
rip_attach(struct socket * so,int proto)510 rip_attach(struct socket *so, int proto)
511 {
512 	struct inpcb *inp;
513 	int error;
514 
515 	KASSERT(sotoinpcb(so) == NULL);
516 	sosetlock(so);
517 
518 	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
519 		error = soreserve(so, rip_sendspace, rip_recvspace);
520 		if (error) {
521 			return error;
522 		}
523 	}
524 
525 	error = inpcb_create(so, &rawcbtable);
526 	if (error) {
527 		return error;
528 	}
529 	inp = sotoinpcb(so);
530 	in4p_ip(inp).ip_p = proto;
531 	KASSERT(solocked(so));
532 
533 	return 0;
534 }
535 
536 static void
rip_detach(struct socket * so)537 rip_detach(struct socket *so)
538 {
539 	struct inpcb *inp;
540 
541 	KASSERT(solocked(so));
542 	inp = sotoinpcb(so);
543 	KASSERT(inp != NULL);
544 
545 #ifdef MROUTING
546 	extern struct socket *ip_mrouter;
547 	if (so == ip_mrouter) {
548 		ip_mrouter_done();
549 	}
550 #endif
551 	inpcb_destroy(inp);
552 }
553 
554 static int
rip_accept(struct socket * so,struct sockaddr * nam)555 rip_accept(struct socket *so, struct sockaddr *nam)
556 {
557 	KASSERT(solocked(so));
558 
559 	panic("rip_accept");
560 
561 	return EOPNOTSUPP;
562 }
563 
564 static int
rip_bind(struct socket * so,struct sockaddr * nam,struct lwp * l)565 rip_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
566 {
567 	struct inpcb *inp = sotoinpcb(so);
568 	struct sockaddr_in *addr = (struct sockaddr_in *)nam;
569 	int error = 0;
570 	int s, ss;
571 	struct ifaddr *ifa;
572 
573 	KASSERT(solocked(so));
574 	KASSERT(inp != NULL);
575 	KASSERT(nam != NULL);
576 
577 	if (addr->sin_len != sizeof(*addr))
578 		return EINVAL;
579 
580 	s = splsoftnet();
581 	if (IFNET_READER_EMPTY()) {
582 		error = EADDRNOTAVAIL;
583 		goto release;
584 	}
585 	if (addr->sin_family != AF_INET) {
586 		error = EAFNOSUPPORT;
587 		goto release;
588 	}
589 	ss = pserialize_read_enter();
590 	if ((ifa = ifa_ifwithaddr(sintosa(addr))) == NULL &&
591 	    (inp->inp_flags & INP_BINDANY) == 0 &&
592 	    !in_nullhost(addr->sin_addr))
593 	{
594 		pserialize_read_exit(ss);
595 		error = EADDRNOTAVAIL;
596 		goto release;
597 	}
598         if (ifa && (ifatoia(ifa))->ia4_flags & IN6_IFF_DUPLICATED) {
599 		pserialize_read_exit(ss);
600 		error = EADDRNOTAVAIL;
601 		goto release;
602 	}
603 	pserialize_read_exit(ss);
604 
605 	in4p_laddr(inp) = addr->sin_addr;
606 
607 release:
608 	splx(s);
609 	return error;
610 }
611 
612 static int
rip_listen(struct socket * so,struct lwp * l)613 rip_listen(struct socket *so, struct lwp *l)
614 {
615 	KASSERT(solocked(so));
616 
617 	return EOPNOTSUPP;
618 }
619 
620 static int
rip_connect(struct socket * so,struct sockaddr * nam,struct lwp * l)621 rip_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
622 {
623 	struct inpcb *inp = sotoinpcb(so);
624 	int error = 0;
625 	int s;
626 
627 	KASSERT(solocked(so));
628 	KASSERT(inp != NULL);
629 	KASSERT(nam != NULL);
630 
631 	s = splsoftnet();
632 	error = rip_connect_pcb(inp, (struct sockaddr_in *)nam);
633 	if (! error)
634 		soisconnected(so);
635 	splx(s);
636 
637 	return error;
638 }
639 
640 static int
rip_connect2(struct socket * so,struct socket * so2)641 rip_connect2(struct socket *so, struct socket *so2)
642 {
643 	KASSERT(solocked(so));
644 
645 	return EOPNOTSUPP;
646 }
647 
648 static int
rip_disconnect(struct socket * so)649 rip_disconnect(struct socket *so)
650 {
651 	struct inpcb *inp = sotoinpcb(so);
652 	int s;
653 
654 	KASSERT(solocked(so));
655 	KASSERT(inp != NULL);
656 
657 	s = splsoftnet();
658 	soisdisconnected(so);
659 	rip_disconnect1(inp);
660 	splx(s);
661 
662 	return 0;
663 }
664 
665 static int
rip_shutdown(struct socket * so)666 rip_shutdown(struct socket *so)
667 {
668 	int s;
669 
670 	KASSERT(solocked(so));
671 
672 	/*
673 	 * Mark the connection as being incapable of further input.
674 	 */
675 	s = splsoftnet();
676 	socantsendmore(so);
677 	splx(s);
678 
679 	return 0;
680 }
681 
682 static int
rip_abort(struct socket * so)683 rip_abort(struct socket *so)
684 {
685 	KASSERT(solocked(so));
686 
687 	panic("rip_abort");
688 
689 	return EOPNOTSUPP;
690 }
691 
692 static int
rip_ioctl(struct socket * so,u_long cmd,void * nam,struct ifnet * ifp)693 rip_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
694 {
695 	return in_control(so, cmd, nam, ifp);
696 }
697 
698 static int
rip_stat(struct socket * so,struct stat * ub)699 rip_stat(struct socket *so, struct stat *ub)
700 {
701 	KASSERT(solocked(so));
702 
703 	/* stat: don't bother with a blocksize. */
704 	return 0;
705 }
706 
707 static int
rip_peeraddr(struct socket * so,struct sockaddr * nam)708 rip_peeraddr(struct socket *so, struct sockaddr *nam)
709 {
710 	int s;
711 
712 	KASSERT(solocked(so));
713 	KASSERT(sotoinpcb(so) != NULL);
714 	KASSERT(nam != NULL);
715 
716 	s = splsoftnet();
717 	inpcb_fetch_peeraddr(sotoinpcb(so), (struct sockaddr_in *)nam);
718 	splx(s);
719 
720 	return 0;
721 }
722 
723 static int
rip_sockaddr(struct socket * so,struct sockaddr * nam)724 rip_sockaddr(struct socket *so, struct sockaddr *nam)
725 {
726 	int s;
727 
728 	KASSERT(solocked(so));
729 	KASSERT(sotoinpcb(so) != NULL);
730 	KASSERT(nam != NULL);
731 
732 	s = splsoftnet();
733 	inpcb_fetch_sockaddr(sotoinpcb(so), (struct sockaddr_in *)nam);
734 	splx(s);
735 
736 	return 0;
737 }
738 
739 static int
rip_rcvd(struct socket * so,int flags,struct lwp * l)740 rip_rcvd(struct socket *so, int flags, struct lwp *l)
741 {
742 	KASSERT(solocked(so));
743 
744 	return EOPNOTSUPP;
745 }
746 
747 static int
rip_recvoob(struct socket * so,struct mbuf * m,int flags)748 rip_recvoob(struct socket *so, struct mbuf *m, int flags)
749 {
750 	KASSERT(solocked(so));
751 
752 	return EOPNOTSUPP;
753 }
754 
755 static int
rip_send(struct socket * so,struct mbuf * m,struct sockaddr * nam,struct mbuf * control,struct lwp * l)756 rip_send(struct socket *so, struct mbuf *m, struct sockaddr *nam,
757     struct mbuf *control, struct lwp *l)
758 {
759 	struct inpcb *inp = sotoinpcb(so);
760 	int error = 0;
761 	int s;
762 
763 	KASSERT(solocked(so));
764 	KASSERT(inp != NULL);
765 	KASSERT(m != NULL);
766 
767 	/*
768 	 * Ship a packet out.  The appropriate raw output
769 	 * routine handles any massaging necessary.
770 	 */
771 	s = splsoftnet();
772 	if (nam) {
773 		if ((so->so_state & SS_ISCONNECTED) != 0) {
774 			error = EISCONN;
775 			goto die;
776 		}
777 		error = rip_connect_pcb(inp, (struct sockaddr_in *)nam);
778 		if (error)
779 			goto die;
780 	} else {
781 		if ((so->so_state & SS_ISCONNECTED) == 0) {
782 			error = ENOTCONN;
783 			goto die;
784 		}
785 	}
786 	error = rip_output(m, inp, control, l);
787 	m = NULL;
788 	control = NULL;
789 	if (nam)
790 		rip_disconnect1(inp);
791  die:
792 	m_freem(m);
793 	m_freem(control);
794 
795 	splx(s);
796 	return error;
797 }
798 
799 static int
rip_sendoob(struct socket * so,struct mbuf * m,struct mbuf * control)800 rip_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
801 {
802 	KASSERT(solocked(so));
803 
804 	m_freem(m);
805 	m_freem(control);
806 
807 	return EOPNOTSUPP;
808 }
809 
810 static int
rip_purgeif(struct socket * so,struct ifnet * ifp)811 rip_purgeif(struct socket *so, struct ifnet *ifp)
812 {
813 	int s;
814 
815 	s = splsoftnet();
816 	mutex_enter(softnet_lock);
817 	inpcb_purgeif0(&rawcbtable, ifp);
818 #ifdef NET_MPSAFE
819 	mutex_exit(softnet_lock);
820 #endif
821 	in_purgeif(ifp);
822 #ifdef NET_MPSAFE
823 	mutex_enter(softnet_lock);
824 #endif
825 	inpcb_purgeif(&rawcbtable, ifp);
826 	mutex_exit(softnet_lock);
827 	splx(s);
828 
829 	return 0;
830 }
831 
832 PR_WRAP_USRREQS(rip)
833 #define	rip_attach	rip_attach_wrapper
834 #define	rip_detach	rip_detach_wrapper
835 #define	rip_accept	rip_accept_wrapper
836 #define	rip_bind	rip_bind_wrapper
837 #define	rip_listen	rip_listen_wrapper
838 #define	rip_connect	rip_connect_wrapper
839 #define	rip_connect2	rip_connect2_wrapper
840 #define	rip_disconnect	rip_disconnect_wrapper
841 #define	rip_shutdown	rip_shutdown_wrapper
842 #define	rip_abort	rip_abort_wrapper
843 #define	rip_ioctl	rip_ioctl_wrapper
844 #define	rip_stat	rip_stat_wrapper
845 #define	rip_peeraddr	rip_peeraddr_wrapper
846 #define	rip_sockaddr	rip_sockaddr_wrapper
847 #define	rip_rcvd	rip_rcvd_wrapper
848 #define	rip_recvoob	rip_recvoob_wrapper
849 #define	rip_send	rip_send_wrapper
850 #define	rip_sendoob	rip_sendoob_wrapper
851 #define	rip_purgeif	rip_purgeif_wrapper
852 
853 const struct pr_usrreqs rip_usrreqs = {
854 	.pr_attach	= rip_attach,
855 	.pr_detach	= rip_detach,
856 	.pr_accept	= rip_accept,
857 	.pr_bind	= rip_bind,
858 	.pr_listen	= rip_listen,
859 	.pr_connect	= rip_connect,
860 	.pr_connect2	= rip_connect2,
861 	.pr_disconnect	= rip_disconnect,
862 	.pr_shutdown	= rip_shutdown,
863 	.pr_abort	= rip_abort,
864 	.pr_ioctl	= rip_ioctl,
865 	.pr_stat	= rip_stat,
866 	.pr_peeraddr	= rip_peeraddr,
867 	.pr_sockaddr	= rip_sockaddr,
868 	.pr_rcvd	= rip_rcvd,
869 	.pr_recvoob	= rip_recvoob,
870 	.pr_send	= rip_send,
871 	.pr_sendoob	= rip_sendoob,
872 	.pr_purgeif	= rip_purgeif,
873 };
874 
875 static void
sysctl_net_inet_raw_setup(struct sysctllog ** clog)876 sysctl_net_inet_raw_setup(struct sysctllog **clog)
877 {
878 
879 	sysctl_createv(clog, 0, NULL, NULL,
880 		       CTLFLAG_PERMANENT,
881 		       CTLTYPE_NODE, "inet", NULL,
882 		       NULL, 0, NULL, 0,
883 		       CTL_NET, PF_INET, CTL_EOL);
884 	sysctl_createv(clog, 0, NULL, NULL,
885 		       CTLFLAG_PERMANENT,
886 		       CTLTYPE_NODE, "raw",
887 		       SYSCTL_DESCR("Raw IPv4 settings"),
888 		       NULL, 0, NULL, 0,
889 		       CTL_NET, PF_INET, IPPROTO_RAW, CTL_EOL);
890 
891 	sysctl_createv(clog, 0, NULL, NULL,
892 		       CTLFLAG_PERMANENT,
893 		       CTLTYPE_STRUCT, "pcblist",
894 		       SYSCTL_DESCR("Raw IPv4 control block list"),
895 		       sysctl_inpcblist, 0, &rawcbtable, 0,
896 		       CTL_NET, PF_INET, IPPROTO_RAW,
897 		       CTL_CREATE, CTL_EOL);
898 }
899