Annotation of src/sys/netinet/raw_ip.c, Revision 1.78.2.1
1.78.2.1! tron 1: /* $NetBSD$ */
1.43 itojun 2:
3: /*
4: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5: * All rights reserved.
1.61 itojun 6: *
1.43 itojun 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.
1.61 itojun 18: *
1.43 itojun 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: */
1.14 cgd 31:
1.1 cgd 32: /*
1.13 mycroft 33: * Copyright (c) 1982, 1986, 1988, 1993
34: * The Regents of the University of California. All rights reserved.
1.1 cgd 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.
1.71 agc 44: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 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: *
1.39 thorpej 60: * @(#)raw_ip.c 8.7 (Berkeley) 5/15/95
1.1 cgd 61: */
1.59 lukem 62:
63: #include <sys/cdefs.h>
1.78.2.1! tron 64: __KERNEL_RCSID(0, "$NetBSD$");
1.40 scottr 65:
1.78 jonathan 66: #include "opt_inet.h"
1.45 thorpej 67: #include "opt_ipsec.h"
1.40 scottr 68: #include "opt_mrouting.h"
1.1 cgd 69:
1.7 mycroft 70: #include <sys/param.h>
71: #include <sys/malloc.h>
72: #include <sys/mbuf.h>
73: #include <sys/socket.h>
74: #include <sys/protosw.h>
75: #include <sys/socketvar.h>
76: #include <sys/errno.h>
1.13 mycroft 77: #include <sys/systm.h>
1.26 mycroft 78: #include <sys/proc.h>
1.1 cgd 79:
1.7 mycroft 80: #include <net/if.h>
81: #include <net/route.h>
1.1 cgd 82:
1.7 mycroft 83: #include <netinet/in.h>
84: #include <netinet/in_systm.h>
85: #include <netinet/ip.h>
86: #include <netinet/ip_var.h>
1.13 mycroft 87: #include <netinet/ip_mroute.h>
1.44 darrenr 88: #include <netinet/ip_icmp.h>
1.7 mycroft 89: #include <netinet/in_pcb.h>
1.24 christos 90: #include <netinet/in_var.h>
91:
92: #include <machine/stdarg.h>
1.13 mycroft 93:
1.43 itojun 94: #ifdef IPSEC
95: #include <netinet6/ipsec.h>
96: #endif /*IPSEC*/
97:
1.72 jonathan 98: #ifdef FAST_IPSEC
99: #include <netipsec/ipsec.h>
1.78.2.1! tron 100: #include <netipsec/ipsec_var.h> /* XXX ipsecstat namespace */
1.72 jonathan 101: #endif /* FAST_IPSEC*/
102:
1.20 mycroft 103: struct inpcbtable rawcbtable;
1.30 pk 104:
1.60 itojun 105: int rip_pcbnotify __P((struct inpcbtable *, struct in_addr,
106: struct in_addr, int, int, void (*) __P((struct inpcb *, int))));
1.30 pk 107: int rip_bind __P((struct inpcb *, struct mbuf *));
108: int rip_connect __P((struct inpcb *, struct mbuf *));
109: void rip_disconnect __P((struct inpcb *));
1.13 mycroft 110:
111: /*
112: * Nominal space allocated to a raw ip socket.
113: */
114: #define RIPSNDQ 8192
115: #define RIPRCVQ 8192
1.1 cgd 116:
117: /*
118: * Raw interface to IP protocol.
119: */
1.13 mycroft 120:
121: /*
122: * Initialize raw connection block q.
123: */
124: void
125: rip_init()
126: {
127:
1.33 mycroft 128: in_pcbinit(&rawcbtable, 1, 1);
1.13 mycroft 129: }
130:
1.1 cgd 131: /*
132: * Setup generic address and protocol structures
133: * for raw_input routine, then pass them along with
134: * mbuf chain.
135: */
1.9 mycroft 136: void
1.24 christos 137: #if __STDC__
138: rip_input(struct mbuf *m, ...)
139: #else
140: rip_input(m, va_alist)
1.1 cgd 141: struct mbuf *m;
1.24 christos 142: va_dcl
143: #endif
1.1 cgd 144: {
1.63 simonb 145: int proto;
1.53 augustss 146: struct ip *ip = mtod(m, struct ip *);
1.75 itojun 147: struct inpcb_hdr *inph;
1.53 augustss 148: struct inpcb *inp;
1.36 thorpej 149: struct inpcb *last = 0;
150: struct mbuf *opts = 0;
1.32 mycroft 151: struct sockaddr_in ripsrc;
1.43 itojun 152: va_list ap;
153:
154: va_start(ap, m);
1.64 simonb 155: (void)va_arg(ap, int); /* ignore value, advance ap */
1.43 itojun 156: proto = va_arg(ap, int);
157: va_end(ap);
1.1 cgd 158:
1.32 mycroft 159: ripsrc.sin_family = AF_INET;
160: ripsrc.sin_len = sizeof(struct sockaddr_in);
1.1 cgd 161: ripsrc.sin_addr = ip->ip_src;
1.34 mycroft 162: ripsrc.sin_port = 0;
163: bzero((caddr_t)ripsrc.sin_zero, sizeof(ripsrc.sin_zero));
1.42 thorpej 164:
165: /*
166: * XXX Compatibility: programs using raw IP expect ip_len
1.62 itojun 167: * XXX to have the header length subtracted, and in host order.
168: * XXX ip_off is also expected to be host order.
1.42 thorpej 169: */
1.62 itojun 170: ip->ip_len = ntohs(ip->ip_len) - (ip->ip_hl << 2);
171: NTOHS(ip->ip_off);
1.32 mycroft 172:
1.75 itojun 173: CIRCLEQ_FOREACH(inph, &rawcbtable.inpt_queue, inph_queue) {
174: inp = (struct inpcb *)inph;
175: if (inp->inp_af != AF_INET)
176: continue;
1.43 itojun 177: if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != proto)
1.13 mycroft 178: continue;
1.32 mycroft 179: if (!in_nullhost(inp->inp_laddr) &&
180: !in_hosteq(inp->inp_laddr, ip->ip_dst))
1.13 mycroft 181: continue;
1.32 mycroft 182: if (!in_nullhost(inp->inp_faddr) &&
183: !in_hosteq(inp->inp_faddr, ip->ip_src))
1.13 mycroft 184: continue;
185: if (last) {
186: struct mbuf *n;
1.55 itojun 187:
1.72 jonathan 188: #if defined(IPSEC) || defined(FAST_IPSEC)
1.55 itojun 189: /* check AH/ESP integrity. */
190: if (ipsec4_in_reject_so(m, last->inp_socket)) {
191: ipsecstat.in_polvio++;
192: /* do not inject data to pcb */
193: } else
194: #endif /*IPSEC*/
1.24 christos 195: if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
1.36 thorpej 196: if (last->inp_flags & INP_CONTROLOPTS ||
197: last->inp_socket->so_options & SO_TIMESTAMP)
198: ip_savecontrol(last, &opts, ip, n);
199: if (sbappendaddr(&last->inp_socket->so_rcv,
200: sintosa(&ripsrc), n, opts) == 0) {
1.13 mycroft 201: /* should notify about lost packet */
202: m_freem(n);
1.36 thorpej 203: if (opts)
204: m_freem(opts);
205: } else
206: sorwakeup(last->inp_socket);
1.41 thorpej 207: opts = NULL;
1.13 mycroft 208: }
209: }
1.36 thorpej 210: last = inp;
1.13 mycroft 211: }
1.72 jonathan 212: #if defined(IPSEC) || defined(FAST_IPSEC)
1.55 itojun 213: /* check AH/ESP integrity. */
214: if (last && ipsec4_in_reject_so(m, last->inp_socket)) {
215: m_freem(m);
216: ipsecstat.in_polvio++;
217: ipstat.ips_delivered--;
218: /* do not inject data to pcb */
219: } else
220: #endif /*IPSEC*/
1.13 mycroft 221: if (last) {
1.36 thorpej 222: if (last->inp_flags & INP_CONTROLOPTS ||
223: last->inp_socket->so_options & SO_TIMESTAMP)
224: ip_savecontrol(last, &opts, ip, m);
225: if (sbappendaddr(&last->inp_socket->so_rcv,
226: sintosa(&ripsrc), m, opts) == 0) {
1.13 mycroft 227: m_freem(m);
1.36 thorpej 228: if (opts)
229: m_freem(opts);
230: } else
231: sorwakeup(last->inp_socket);
1.13 mycroft 232: } else {
1.44 darrenr 233: if (inetsw[ip_protox[ip->ip_p]].pr_input == rip_input) {
1.47 itojun 234: icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL,
235: 0, 0);
1.44 darrenr 236: ipstat.ips_noproto++;
237: ipstat.ips_delivered--;
238: } else
239: m_freem(m);
1.1 cgd 240: }
1.43 itojun 241: return;
1.60 itojun 242: }
243:
244: int
245: rip_pcbnotify(table, faddr, laddr, proto, errno, notify)
246: struct inpcbtable *table;
247: struct in_addr faddr, laddr;
248: int proto;
249: int errno;
250: void (*notify) __P((struct inpcb *, int));
251: {
252: struct inpcb *inp, *ninp;
253: int nmatch;
254:
255: nmatch = 0;
1.75 itojun 256: for (inp = (struct inpcb *)CIRCLEQ_FIRST(&table->inpt_queue);
1.60 itojun 257: inp != (struct inpcb *)&table->inpt_queue;
258: inp = ninp) {
1.75 itojun 259: ninp = (struct inpcb *)inp->inp_queue.cqe_next;
260: if (inp->inp_af != AF_INET)
261: continue;
1.60 itojun 262: if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != proto)
263: continue;
264: if (in_hosteq(inp->inp_faddr, faddr) &&
265: in_hosteq(inp->inp_laddr, laddr)) {
266: (*notify)(inp, errno);
267: nmatch++;
268: }
269: }
270:
271: return nmatch;
272: }
273:
274: void *
275: rip_ctlinput(cmd, sa, v)
276: int cmd;
277: struct sockaddr *sa;
278: void *v;
279: {
280: struct ip *ip = v;
281: void (*notify) __P((struct inpcb *, int)) = in_rtchange;
282: int errno;
283:
284: if (sa->sa_family != AF_INET ||
285: sa->sa_len != sizeof(struct sockaddr_in))
286: return NULL;
287: if ((unsigned)cmd >= PRC_NCMDS)
288: return NULL;
289: errno = inetctlerrmap[cmd];
290: if (PRC_IS_REDIRECT(cmd))
291: notify = in_rtchange, ip = 0;
292: else if (cmd == PRC_HOSTDEAD)
293: ip = 0;
294: else if (errno == 0)
295: return NULL;
296: if (ip) {
297: rip_pcbnotify(&rawcbtable, satosin(sa)->sin_addr,
298: ip->ip_src, ip->ip_p, errno, notify);
299:
300: /* XXX mapped address case */
301: } else
302: in_pcbnotifyall(&rawcbtable, satosin(sa)->sin_addr, errno,
303: notify);
304: return NULL;
1.1 cgd 305: }
306:
307: /*
308: * Generate IP header and pass packet to ip_output.
309: * Tack on options user may have setup with control call.
310: */
1.9 mycroft 311: int
1.24 christos 312: #if __STDC__
313: rip_output(struct mbuf *m, ...)
314: #else
315: rip_output(m, va_alist)
316: struct mbuf *m;
317: va_dcl
318: #endif
319: {
1.53 augustss 320: struct inpcb *inp;
321: struct ip *ip;
1.10 mycroft 322: struct mbuf *opts;
1.24 christos 323: int flags;
324: va_list ap;
325:
326: va_start(ap, m);
1.27 mycroft 327: inp = va_arg(ap, struct inpcb *);
1.24 christos 328: va_end(ap);
329:
1.27 mycroft 330: flags =
1.37 matt 331: (inp->inp_socket->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST
332: | IP_RETURNMTU;
1.1 cgd 333:
334: /*
335: * If the user handed us a complete IP packet, use it.
336: * Otherwise, allocate an mbuf for a header and fill it in.
337: */
1.13 mycroft 338: if ((inp->inp_flags & INP_HDRINCL) == 0) {
1.35 thorpej 339: if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) {
340: m_freem(m);
341: return (EMSGSIZE);
342: }
1.68 itojun 343: M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
344: if (!m)
345: return (ENOBUFS);
1.1 cgd 346: ip = mtod(m, struct ip *);
347: ip->ip_tos = 0;
1.62 itojun 348: ip->ip_off = htons(0);
1.13 mycroft 349: ip->ip_p = inp->inp_ip.ip_p;
1.62 itojun 350: ip->ip_len = htons(m->m_pkthdr.len);
1.13 mycroft 351: ip->ip_src = inp->inp_laddr;
1.27 mycroft 352: ip->ip_dst = inp->inp_faddr;
1.1 cgd 353: ip->ip_ttl = MAXTTL;
1.13 mycroft 354: opts = inp->inp_options;
355: } else {
1.35 thorpej 356: if (m->m_pkthdr.len > IP_MAXPACKET) {
357: m_freem(m);
358: return (EMSGSIZE);
359: }
1.13 mycroft 360: ip = mtod(m, struct ip *);
1.65 thorpej 361:
362: /*
363: * If the mbuf is read-only, we need to allocate
364: * a new mbuf for the header, since we need to
365: * modify the header.
366: */
367: if (M_READONLY(m)) {
368: int hlen = ip->ip_hl << 2;
369:
370: m = m_copyup(m, hlen, (max_linkhdr + 3) & ~3);
371: if (m == NULL)
372: return (ENOMEM); /* XXX */
373: ip = mtod(m, struct ip *);
374: }
375:
1.62 itojun 376: /* XXX userland passes ip_len and ip_off in host order */
1.38 mycroft 377: if (m->m_pkthdr.len != ip->ip_len) {
378: m_freem(m);
379: return (EINVAL);
380: }
1.62 itojun 381: HTONS(ip->ip_len);
382: HTONS(ip->ip_off);
1.13 mycroft 383: if (ip->ip_id == 0)
1.77 jonathan 384: ip->ip_id = ip_newid();
1.13 mycroft 385: opts = NULL;
386: /* XXX prevent ip_output from overwriting header fields */
387: flags |= IP_RAWOUTPUT;
388: ipstat.ips_rawout++;
1.1 cgd 389: }
1.62 itojun 390: return (ip_output(m, opts, &inp->inp_route, flags, inp->inp_moptions,
1.73 itojun 391: inp->inp_socket, &inp->inp_errormtu));
1.1 cgd 392: }
393:
394: /*
395: * Raw IP socket option processing.
396: */
1.9 mycroft 397: int
1.1 cgd 398: rip_ctloutput(op, so, level, optname, m)
399: int op;
400: struct socket *so;
401: int level, optname;
402: struct mbuf **m;
403: {
1.53 augustss 404: struct inpcb *inp = sotoinpcb(so);
1.31 mycroft 405: int error = 0;
1.1 cgd 406:
1.15 mycroft 407: if (level != IPPROTO_IP) {
1.31 mycroft 408: error = ENOPROTOOPT;
409: if (op == PRCO_SETOPT && *m != 0)
410: (void) m_free(*m);
411: } else switch (op) {
412:
413: case PRCO_SETOPT:
414: switch (optname) {
415: case IP_HDRINCL:
416: if (*m == 0 || (*m)->m_len < sizeof (int))
417: error = EINVAL;
418: else {
1.13 mycroft 419: if (*mtod(*m, int *))
420: inp->inp_flags |= INP_HDRINCL;
421: else
422: inp->inp_flags &= ~INP_HDRINCL;
423: }
1.31 mycroft 424: if (*m != 0)
425: (void) m_free(*m);
426: break;
427:
428: #ifdef MROUTING
429: case MRT_INIT:
430: case MRT_DONE:
431: case MRT_ADD_VIF:
432: case MRT_DEL_VIF:
433: case MRT_ADD_MFC:
434: case MRT_DEL_MFC:
435: case MRT_ASSERT:
436: error = ip_mrouter_set(so, optname, m);
437: break;
438: #endif
439:
440: default:
441: error = ip_ctloutput(op, so, level, optname, m);
442: break;
1.13 mycroft 443: }
444: break;
1.1 cgd 445:
1.31 mycroft 446: case PRCO_GETOPT:
447: switch (optname) {
448: case IP_HDRINCL:
1.66 thorpej 449: *m = m_get(M_WAIT, MT_SOOPTS);
1.67 matt 450: MCLAIM((*m), so->so_mowner);
1.31 mycroft 451: (*m)->m_len = sizeof (int);
452: *mtod(*m, int *) = inp->inp_flags & INP_HDRINCL ? 1 : 0;
453: break;
454:
1.6 hpeyerl 455: #ifdef MROUTING
1.31 mycroft 456: case MRT_VERSION:
457: case MRT_ASSERT:
458: error = ip_mrouter_get(so, optname, m);
1.18 mycroft 459: break;
1.31 mycroft 460: #endif
461:
1.18 mycroft 462: default:
1.31 mycroft 463: error = ip_ctloutput(op, so, level, optname, m);
1.18 mycroft 464: break;
465: }
1.31 mycroft 466: break;
1.1 cgd 467: }
1.31 mycroft 468: return (error);
1.1 cgd 469: }
470:
1.27 mycroft 471: int
1.29 mycroft 472: rip_bind(inp, nam)
473: struct inpcb *inp;
474: struct mbuf *nam;
475: {
476: struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
477:
478: if (nam->m_len != sizeof(*addr))
479: return (EINVAL);
1.58 matt 480: if (TAILQ_FIRST(&ifnet) == 0)
1.29 mycroft 481: return (EADDRNOTAVAIL);
482: if (addr->sin_family != AF_INET &&
483: addr->sin_family != AF_IMPLINK)
484: return (EAFNOSUPPORT);
1.32 mycroft 485: if (!in_nullhost(addr->sin_addr) &&
1.29 mycroft 486: ifa_ifwithaddr(sintosa(addr)) == 0)
487: return (EADDRNOTAVAIL);
488: inp->inp_laddr = addr->sin_addr;
489: return (0);
490: }
491:
492: int
1.27 mycroft 493: rip_connect(inp, nam)
494: struct inpcb *inp;
495: struct mbuf *nam;
496: {
497: struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
498:
499: if (nam->m_len != sizeof(*addr))
500: return (EINVAL);
1.58 matt 501: if (TAILQ_FIRST(&ifnet) == 0)
1.27 mycroft 502: return (EADDRNOTAVAIL);
503: if (addr->sin_family != AF_INET &&
504: addr->sin_family != AF_IMPLINK)
505: return (EAFNOSUPPORT);
506: inp->inp_faddr = addr->sin_addr;
507: return (0);
508: }
509:
510: void
511: rip_disconnect(inp)
512: struct inpcb *inp;
513: {
514:
1.32 mycroft 515: inp->inp_faddr = zeroin_addr;
1.27 mycroft 516: }
517:
1.13 mycroft 518: u_long rip_sendspace = RIPSNDQ;
519: u_long rip_recvspace = RIPRCVQ;
520:
1.1 cgd 521: /*ARGSUSED*/
1.9 mycroft 522: int
1.70 fvdl 523: rip_usrreq(so, req, m, nam, control, p)
1.53 augustss 524: struct socket *so;
1.1 cgd 525: int req;
1.2 cgd 526: struct mbuf *m, *nam, *control;
1.70 fvdl 527: struct proc *p;
1.1 cgd 528: {
1.53 augustss 529: struct inpcb *inp;
1.27 mycroft 530: int s;
1.53 augustss 531: int error = 0;
1.13 mycroft 532: #ifdef MROUTING
1.6 hpeyerl 533: extern struct socket *ip_mrouter;
534: #endif
1.27 mycroft 535:
1.22 pk 536: if (req == PRU_CONTROL)
537: return (in_control(so, (long)m, (caddr_t)nam,
1.26 mycroft 538: (struct ifnet *)control, p));
1.49 thorpej 539:
1.50 thorpej 540: if (req == PRU_PURGEIF) {
1.56 itojun 541: in_pcbpurgeif0(&rawcbtable, (struct ifnet *)control);
1.50 thorpej 542: in_purgeif((struct ifnet *)control);
543: in_pcbpurgeif(&rawcbtable, (struct ifnet *)control);
1.49 thorpej 544: return (0);
545: }
1.22 pk 546:
1.27 mycroft 547: s = splsoftnet();
548: inp = sotoinpcb(so);
1.28 mycroft 549: #ifdef DIAGNOSTIC
550: if (req != PRU_SEND && req != PRU_SENDOOB && control)
551: panic("rip_usrreq: unexpected control mbuf");
552: #endif
1.27 mycroft 553: if (inp == 0 && req != PRU_ATTACH) {
1.22 pk 554: error = EINVAL;
555: goto release;
556: }
557:
1.1 cgd 558: switch (req) {
559:
560: case PRU_ATTACH:
1.27 mycroft 561: if (inp != 0) {
562: error = EISCONN;
563: break;
564: }
1.26 mycroft 565: if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag))) {
1.13 mycroft 566: error = EACCES;
567: break;
568: }
1.27 mycroft 569: if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
570: error = soreserve(so, rip_sendspace, rip_recvspace);
571: if (error)
572: break;
573: }
574: error = in_pcballoc(so, &rawcbtable);
575: if (error)
1.13 mycroft 576: break;
1.27 mycroft 577: inp = sotoinpcb(so);
1.17 cgd 578: inp->inp_ip.ip_p = (long)nam;
1.1 cgd 579: break;
580:
581: case PRU_DETACH:
1.13 mycroft 582: #ifdef MROUTING
1.6 hpeyerl 583: if (so == ip_mrouter)
584: ip_mrouter_done();
585: #endif
1.13 mycroft 586: in_pcbdetach(inp);
1.1 cgd 587: break;
588:
589: case PRU_BIND:
1.29 mycroft 590: error = rip_bind(inp, nam);
1.27 mycroft 591: break;
592:
593: case PRU_LISTEN:
594: error = EOPNOTSUPP;
595: break;
596:
597: case PRU_CONNECT:
598: error = rip_connect(inp, nam);
599: if (error)
1.13 mycroft 600: break;
1.1 cgd 601: soisconnected(so);
1.13 mycroft 602: break;
603:
604: case PRU_CONNECT2:
605: error = EOPNOTSUPP;
606: break;
607:
1.27 mycroft 608: case PRU_DISCONNECT:
609: soisdisconnected(so);
610: rip_disconnect(inp);
611: break;
612:
1.13 mycroft 613: /*
614: * Mark the connection as being incapable of further input.
615: */
616: case PRU_SHUTDOWN:
617: socantsendmore(so);
618: break;
619:
1.27 mycroft 620: case PRU_RCVD:
621: error = EOPNOTSUPP;
622: break;
623:
1.13 mycroft 624: /*
625: * Ship a packet out. The appropriate raw output
626: * routine handles any massaging necessary.
627: */
628: case PRU_SEND:
1.28 mycroft 629: if (control && control->m_len) {
630: m_freem(control);
631: m_freem(m);
632: error = EINVAL;
633: break;
634: }
635: {
1.27 mycroft 636: if (nam) {
637: if ((so->so_state & SS_ISCONNECTED) != 0) {
1.13 mycroft 638: error = EISCONN;
1.28 mycroft 639: goto die;
1.13 mycroft 640: }
1.27 mycroft 641: error = rip_connect(inp, nam);
642: if (error) {
1.28 mycroft 643: die:
1.27 mycroft 644: m_freem(m);
645: break;
646: }
1.13 mycroft 647: } else {
1.27 mycroft 648: if ((so->so_state & SS_ISCONNECTED) == 0) {
1.13 mycroft 649: error = ENOTCONN;
1.28 mycroft 650: goto die;
1.13 mycroft 651: }
652: }
1.27 mycroft 653: error = rip_output(m, inp);
654: if (nam)
655: rip_disconnect(inp);
1.28 mycroft 656: }
1.13 mycroft 657: break;
658:
659: case PRU_SENSE:
660: /*
661: * stat: don't bother with a blocksize.
662: */
1.27 mycroft 663: splx(s);
1.1 cgd 664: return (0);
1.13 mycroft 665:
666: case PRU_RCVOOB:
1.27 mycroft 667: error = EOPNOTSUPP;
668: break;
669:
1.13 mycroft 670: case PRU_SENDOOB:
1.28 mycroft 671: m_freem(control);
1.27 mycroft 672: m_freem(m);
1.13 mycroft 673: error = EOPNOTSUPP;
674: break;
675:
676: case PRU_SOCKADDR:
677: in_setsockaddr(inp, nam);
678: break;
679:
680: case PRU_PEERADDR:
681: in_setpeeraddr(inp, nam);
682: break;
683:
684: default:
685: panic("rip_usrreq");
1.1 cgd 686: }
1.27 mycroft 687:
1.22 pk 688: release:
1.27 mycroft 689: splx(s);
1.1 cgd 690: return (error);
691: }
CVSweb <webmaster@jp.NetBSD.org>