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