123202Smckusick /*
263231Sbostic * Copyright (c) 1984, 1985, 1986, 1987, 1993
363231Sbostic * The Regents of the University of California. All rights reserved.
423202Smckusick *
544498Sbostic * %sccs.include.redist.c%
633371Ssklower *
7*68167Scgd * @(#)idp_usrreq.c 8.2 (Berkeley) 01/09/95
823202Smckusick */
921479Ssklower
1056534Sbostic #include <sys/param.h>
1156534Sbostic #include <sys/malloc.h>
1256534Sbostic #include <sys/mbuf.h>
1356534Sbostic #include <sys/protosw.h>
1456534Sbostic #include <sys/socket.h>
1556534Sbostic #include <sys/socketvar.h>
1656534Sbostic #include <sys/errno.h>
1756534Sbostic #include <sys/stat.h>
1821479Ssklower
1956534Sbostic #include <net/if.h>
2056534Sbostic #include <net/route.h>
2121479Ssklower
2256534Sbostic #include <netns/ns.h>
2356534Sbostic #include <netns/ns_pcb.h>
2456534Sbostic #include <netns/ns_if.h>
2556534Sbostic #include <netns/idp.h>
2656534Sbostic #include <netns/idp_var.h>
2756534Sbostic #include <netns/ns_error.h>
2821479Ssklower
2921479Ssklower /*
3021479Ssklower * IDP protocol implementation.
3121479Ssklower */
3221479Ssklower
3337473Ssklower struct sockaddr_ns idp_ns = { sizeof(idp_ns), AF_NS };
3421479Ssklower
3523977Ssklower /*
3623977Ssklower * This may also be called for raw listeners.
3723977Ssklower */
3835797Ssklower idp_input(m, nsp)
3921479Ssklower struct mbuf *m;
4021479Ssklower register struct nspcb *nsp;
4121479Ssklower {
4221479Ssklower register struct idp *idp = mtod(m, struct idp *);
4335797Ssklower struct ifnet *ifp = m->m_pkthdr.rcvif;
4421479Ssklower
4524611Ssklower if (nsp==0)
4624049Ssklower panic("No nspcb");
4721479Ssklower /*
4821479Ssklower * Construct sockaddr format source address.
4921479Ssklower * Stuff source address and datagram in user buffer.
5021479Ssklower */
5121479Ssklower idp_ns.sns_addr = idp->idp_sna;
5226055Ssklower if (ns_neteqnn(idp->idp_sna.x_net, ns_zeronet) && ifp) {
5337473Ssklower register struct ifaddr *ifa;
5424611Ssklower
5537473Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
5637473Ssklower if (ifa->ifa_addr->sa_family == AF_NS) {
5724611Ssklower idp_ns.sns_addr.x_net =
5837473Ssklower IA_SNS(ifa)->sns_addr.x_net;
5924611Ssklower break;
6024611Ssklower }
6124611Ssklower }
6224611Ssklower }
6321479Ssklower nsp->nsp_rpt = idp->idp_pt;
6421479Ssklower if ( ! (nsp->nsp_flags & NSP_RAWIN) ) {
6521479Ssklower m->m_len -= sizeof (struct idp);
6635797Ssklower m->m_pkthdr.len -= sizeof (struct idp);
6735797Ssklower m->m_data += sizeof (struct idp);
6821479Ssklower }
6921479Ssklower if (sbappendaddr(&nsp->nsp_socket->so_rcv, (struct sockaddr *)&idp_ns,
7021479Ssklower m, (struct mbuf *)0) == 0)
7121479Ssklower goto bad;
7221479Ssklower sorwakeup(nsp->nsp_socket);
7321479Ssklower return;
7421479Ssklower bad:
7521479Ssklower m_freem(m);
7621479Ssklower }
7721479Ssklower
7821479Ssklower idp_abort(nsp)
7921479Ssklower struct nspcb *nsp;
8021479Ssklower {
8121479Ssklower struct socket *so = nsp->nsp_socket;
8221479Ssklower
8321479Ssklower ns_pcbdisconnect(nsp);
8421479Ssklower soisdisconnected(so);
8521479Ssklower }
8623977Ssklower /*
8723977Ssklower * Drop connection, reporting
8823977Ssklower * the specified error.
8923977Ssklower */
9023977Ssklower struct nspcb *
idp_drop(nsp,errno)9123977Ssklower idp_drop(nsp, errno)
9223977Ssklower register struct nspcb *nsp;
9323977Ssklower int errno;
9423977Ssklower {
9523977Ssklower struct socket *so = nsp->nsp_socket;
9621479Ssklower
9723977Ssklower /*
9823977Ssklower * someday, in the xerox world
9923977Ssklower * we will generate error protocol packets
10023977Ssklower * announcing that the socket has gone away.
10123977Ssklower */
10223977Ssklower /*if (TCPS_HAVERCVDSYN(tp->t_state)) {
10323977Ssklower tp->t_state = TCPS_CLOSED;
10423977Ssklower (void) tcp_output(tp);
10523977Ssklower }*/
10623977Ssklower so->so_error = errno;
10723977Ssklower ns_pcbdisconnect(nsp);
10823977Ssklower soisdisconnected(so);
10923977Ssklower }
11023977Ssklower
11125042Ssklower int noIdpRoute;
11221479Ssklower idp_output(nsp, m0)
11321479Ssklower struct nspcb *nsp;
11421479Ssklower struct mbuf *m0;
11521479Ssklower {
11621479Ssklower register struct mbuf *m;
11721479Ssklower register struct idp *idp;
11821479Ssklower register struct socket *so;
11921479Ssklower register int len = 0;
12021479Ssklower register struct route *ro;
12121479Ssklower struct mbuf *mprev;
12221479Ssklower extern int idpcksum;
12321479Ssklower
12421479Ssklower /*
12521479Ssklower * Calculate data length.
12621479Ssklower */
12721479Ssklower for (m = m0; m; m = m->m_next) {
12821479Ssklower mprev = m;
12921479Ssklower len += m->m_len;
13021479Ssklower }
13121479Ssklower /*
13221479Ssklower * Make sure packet is actually of even length.
13321479Ssklower */
13421479Ssklower
13521479Ssklower if (len & 1) {
13621479Ssklower m = mprev;
13735797Ssklower if ((m->m_flags & M_EXT) == 0 &&
13835797Ssklower (m->m_len + m->m_data < &m->m_dat[MLEN])) {
13921479Ssklower m->m_len++;
14021479Ssklower } else {
14121479Ssklower struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA);
14221479Ssklower
14321699Ssklower if (m1 == 0) {
14421699Ssklower m_freem(m0);
14521699Ssklower return (ENOBUFS);
14621699Ssklower }
14721479Ssklower m1->m_len = 1;
14821479Ssklower * mtod(m1, char *) = 0;
14921479Ssklower m->m_next = m1;
15021479Ssklower }
15135797Ssklower m0->m_pkthdr.len++;
15221479Ssklower }
15321479Ssklower
15421479Ssklower /*
15521479Ssklower * Fill in mbuf with extended IDP header
15621479Ssklower * and addresses and length put into network format.
15721479Ssklower */
15835797Ssklower m = m0;
15921479Ssklower if (nsp->nsp_flags & NSP_RAWOUT) {
16021479Ssklower idp = mtod(m, struct idp *);
16121479Ssklower } else {
16235797Ssklower M_PREPEND(m, sizeof (struct idp), M_DONTWAIT);
16335797Ssklower if (m == 0)
16421479Ssklower return (ENOBUFS);
16521479Ssklower idp = mtod(m, struct idp *);
16621479Ssklower idp->idp_tc = 0;
16721479Ssklower idp->idp_pt = nsp->nsp_dpt;
16821479Ssklower idp->idp_sna = nsp->nsp_laddr;
16921479Ssklower idp->idp_dna = nsp->nsp_faddr;
17021479Ssklower len += sizeof (struct idp);
17121479Ssklower }
17221479Ssklower
17321479Ssklower idp->idp_len = htons((u_short)len);
17421479Ssklower
17521479Ssklower if (idpcksum) {
17621479Ssklower idp->idp_sum = 0;
17721479Ssklower len = ((len - 1) | 1) + 1;
17821479Ssklower idp->idp_sum = ns_cksum(m, len);
17921479Ssklower } else
18021479Ssklower idp->idp_sum = 0xffff;
18121479Ssklower
18221479Ssklower /*
18321479Ssklower * Output datagram.
18421479Ssklower */
18521479Ssklower so = nsp->nsp_socket;
18621479Ssklower if (so->so_options & SO_DONTROUTE)
18721479Ssklower return (ns_output(m, (struct route *)0,
18821479Ssklower (so->so_options & SO_BROADCAST) | NS_ROUTETOIF));
18921479Ssklower /*
19021479Ssklower * Use cached route for previous datagram if
19125042Ssklower * possible. If the previous net was the same
19225042Ssklower * and the interface was a broadcast medium, or
19325042Ssklower * if the previous destination was identical,
19425042Ssklower * then we are ok.
19521479Ssklower *
19621479Ssklower * NB: We don't handle broadcasts because that
19721479Ssklower * would require 3 subroutine calls.
19821479Ssklower */
19921479Ssklower ro = &nsp->nsp_route;
20025042Ssklower #ifdef ancient_history
20125042Ssklower /*
20225042Ssklower * I think that this will all be handled in ns_pcbconnect!
20325042Ssklower */
20425042Ssklower if (ro->ro_rt) {
20525042Ssklower if(ns_neteq(nsp->nsp_lastdst, idp->idp_dna)) {
20625042Ssklower /*
20725042Ssklower * This assumes we have no GH type routes
20825042Ssklower */
20925042Ssklower if (ro->ro_rt->rt_flags & RTF_HOST) {
21025042Ssklower if (!ns_hosteq(nsp->nsp_lastdst, idp->idp_dna))
21125042Ssklower goto re_route;
21225042Ssklower
21325042Ssklower }
21425042Ssklower if ((ro->ro_rt->rt_flags & RTF_GATEWAY) == 0) {
21525042Ssklower register struct ns_addr *dst =
21625042Ssklower &satons_addr(ro->ro_dst);
21725042Ssklower dst->x_host = idp->idp_dna.x_host;
21825042Ssklower }
21925042Ssklower /*
22025042Ssklower * Otherwise, we go through the same gateway
22125042Ssklower * and dst is already set up.
22225042Ssklower */
22325042Ssklower } else {
22425042Ssklower re_route:
22525042Ssklower RTFREE(ro->ro_rt);
22625042Ssklower ro->ro_rt = (struct rtentry *)0;
22725042Ssklower }
22821479Ssklower }
22925042Ssklower nsp->nsp_lastdst = idp->idp_dna;
23060358Sbostic #endif /* ancient_history */
23125042Ssklower if (noIdpRoute) ro = 0;
23221479Ssklower return (ns_output(m, ro, so->so_options & SO_BROADCAST));
23321479Ssklower }
23424225Ssklower /* ARGSUSED */
idp_ctloutput(req,so,level,name,value)23521479Ssklower idp_ctloutput(req, so, level, name, value)
23621479Ssklower int req, level;
23721479Ssklower struct socket *so;
23821479Ssklower int name;
23921479Ssklower struct mbuf **value;
24021479Ssklower {
24121479Ssklower register struct mbuf *m;
24221479Ssklower struct nspcb *nsp = sotonspcb(so);
24321479Ssklower int mask, error = 0;
24423977Ssklower extern long ns_pexseq;
24521479Ssklower
24623500Ssklower if (nsp == NULL)
24723500Ssklower return (EINVAL);
24821479Ssklower
24921479Ssklower switch (req) {
25023500Ssklower
25121479Ssklower case PRCO_GETOPT:
25223500Ssklower if (value==NULL)
25323500Ssklower return (EINVAL);
25421479Ssklower m = m_get(M_DONTWAIT, MT_DATA);
25523500Ssklower if (m==NULL)
25623500Ssklower return (ENOBUFS);
25721479Ssklower switch (name) {
25823500Ssklower
25924049Ssklower case SO_ALL_PACKETS:
26024049Ssklower mask = NSP_ALL_PACKETS;
26124049Ssklower goto get_flags;
26224049Ssklower
26321479Ssklower case SO_HEADERS_ON_INPUT:
26421479Ssklower mask = NSP_RAWIN;
26521479Ssklower goto get_flags;
26623500Ssklower
26721479Ssklower case SO_HEADERS_ON_OUTPUT:
26821479Ssklower mask = NSP_RAWOUT;
26921479Ssklower get_flags:
27021479Ssklower m->m_len = sizeof(short);
27121479Ssklower *mtod(m, short *) = nsp->nsp_flags & mask;
27221479Ssklower break;
27323500Ssklower
27421479Ssklower case SO_DEFAULT_HEADERS:
27521479Ssklower m->m_len = sizeof(struct idp);
27621479Ssklower {
27721479Ssklower register struct idp *idp = mtod(m, struct idp *);
27821479Ssklower idp->idp_len = 0;
27921479Ssklower idp->idp_sum = 0;
28021479Ssklower idp->idp_tc = 0;
28121479Ssklower idp->idp_pt = nsp->nsp_dpt;
28221479Ssklower idp->idp_dna = nsp->nsp_faddr;
28321479Ssklower idp->idp_sna = nsp->nsp_laddr;
28421479Ssklower }
28523977Ssklower break;
28623977Ssklower
28723977Ssklower case SO_SEQNO:
28823977Ssklower m->m_len = sizeof(long);
28923977Ssklower *mtod(m, long *) = ns_pexseq++;
29025335Ssklower break;
29125335Ssklower
29225335Ssklower default:
29325335Ssklower error = EINVAL;
29421479Ssklower }
29521479Ssklower *value = m;
29621479Ssklower break;
29723500Ssklower
29821479Ssklower case PRCO_SETOPT:
29921479Ssklower switch (name) {
30024225Ssklower int *ok;
30121479Ssklower
30224049Ssklower case SO_ALL_PACKETS:
30324049Ssklower mask = NSP_ALL_PACKETS;
30424049Ssklower goto set_head;
30524049Ssklower
30621479Ssklower case SO_HEADERS_ON_INPUT:
30721479Ssklower mask = NSP_RAWIN;
30821479Ssklower goto set_head;
30923500Ssklower
31021479Ssklower case SO_HEADERS_ON_OUTPUT:
31121479Ssklower mask = NSP_RAWOUT;
31221479Ssklower set_head:
31321479Ssklower if (value && *value) {
31421479Ssklower ok = mtod(*value, int *);
31521479Ssklower if (*ok)
31621479Ssklower nsp->nsp_flags |= mask;
31721479Ssklower else
31821479Ssklower nsp->nsp_flags &= ~mask;
31921479Ssklower } else error = EINVAL;
32021479Ssklower break;
32123500Ssklower
32221479Ssklower case SO_DEFAULT_HEADERS:
32321479Ssklower {
32421479Ssklower register struct idp *idp
32521479Ssklower = mtod(*value, struct idp *);
32621479Ssklower nsp->nsp_dpt = idp->idp_pt;
32721479Ssklower }
32825335Ssklower break;
32921479Ssklower #ifdef NSIP
33023500Ssklower
33121479Ssklower case SO_NSIP_ROUTE:
33221479Ssklower error = nsip_route(*value);
33325335Ssklower break;
33460358Sbostic #endif /* NSIP */
33525335Ssklower default:
33625335Ssklower error = EINVAL;
33721479Ssklower }
33821479Ssklower if (value && *value)
33921479Ssklower m_freem(*value);
34021479Ssklower break;
34121479Ssklower }
34223500Ssklower return (error);
34321479Ssklower }
34421479Ssklower
34521479Ssklower /*ARGSUSED*/
34641921Ssklower idp_usrreq(so, req, m, nam, control)
34721479Ssklower struct socket *so;
34821479Ssklower int req;
34941921Ssklower struct mbuf *m, *nam, *control;
35021479Ssklower {
35121479Ssklower struct nspcb *nsp = sotonspcb(so);
35221479Ssklower int error = 0;
35321479Ssklower
35421479Ssklower if (req == PRU_CONTROL)
355*68167Scgd return (ns_control(so, m, (caddr_t)nam,
35641921Ssklower (struct ifnet *)control));
35741921Ssklower if (control && control->m_len) {
35821479Ssklower error = EINVAL;
35921479Ssklower goto release;
36021479Ssklower }
36121479Ssklower if (nsp == NULL && req != PRU_ATTACH) {
36221479Ssklower error = EINVAL;
36321479Ssklower goto release;
36421479Ssklower }
36521479Ssklower switch (req) {
36621479Ssklower
36721479Ssklower case PRU_ATTACH:
36821479Ssklower if (nsp != NULL) {
36921479Ssklower error = EINVAL;
37021479Ssklower break;
37121479Ssklower }
37221479Ssklower error = ns_pcballoc(so, &nspcb);
37321479Ssklower if (error)
37421479Ssklower break;
37534500Skarels error = soreserve(so, (u_long) 2048, (u_long) 2048);
37621479Ssklower if (error)
37721479Ssklower break;
37821479Ssklower break;
37921479Ssklower
38021479Ssklower case PRU_DETACH:
38121479Ssklower if (nsp == NULL) {
38221479Ssklower error = ENOTCONN;
38321479Ssklower break;
38421479Ssklower }
38521479Ssklower ns_pcbdetach(nsp);
38621479Ssklower break;
38721479Ssklower
38821479Ssklower case PRU_BIND:
38921479Ssklower error = ns_pcbbind(nsp, nam);
39021479Ssklower break;
39121479Ssklower
39221479Ssklower case PRU_LISTEN:
39321479Ssklower error = EOPNOTSUPP;
39421479Ssklower break;
39521479Ssklower
39621479Ssklower case PRU_CONNECT:
39721479Ssklower if (!ns_nullhost(nsp->nsp_faddr)) {
39821479Ssklower error = EISCONN;
39921479Ssklower break;
40021479Ssklower }
40121479Ssklower error = ns_pcbconnect(nsp, nam);
40221479Ssklower if (error == 0)
40321479Ssklower soisconnected(so);
40421479Ssklower break;
40521479Ssklower
40621479Ssklower case PRU_CONNECT2:
40721479Ssklower error = EOPNOTSUPP;
40821479Ssklower break;
40921479Ssklower
41021479Ssklower case PRU_ACCEPT:
41121479Ssklower error = EOPNOTSUPP;
41221479Ssklower break;
41321479Ssklower
41421479Ssklower case PRU_DISCONNECT:
41521479Ssklower if (ns_nullhost(nsp->nsp_faddr)) {
41621479Ssklower error = ENOTCONN;
41721479Ssklower break;
41821479Ssklower }
41921479Ssklower ns_pcbdisconnect(nsp);
42021479Ssklower soisdisconnected(so);
42121479Ssklower break;
42221479Ssklower
42321479Ssklower case PRU_SHUTDOWN:
42421479Ssklower socantsendmore(so);
42521479Ssklower break;
42621479Ssklower
42721479Ssklower case PRU_SEND:
42821479Ssklower {
42921479Ssklower struct ns_addr laddr;
43021479Ssklower int s;
43121479Ssklower
43221479Ssklower if (nam) {
43321479Ssklower laddr = nsp->nsp_laddr;
43421479Ssklower if (!ns_nullhost(nsp->nsp_faddr)) {
43521479Ssklower error = EISCONN;
43621479Ssklower break;
43721479Ssklower }
43821479Ssklower /*
43921479Ssklower * Must block input while temporarily connected.
44021479Ssklower */
44121479Ssklower s = splnet();
44221479Ssklower error = ns_pcbconnect(nsp, nam);
44321479Ssklower if (error) {
44421479Ssklower splx(s);
44521479Ssklower break;
44621479Ssklower }
44721479Ssklower } else {
44821479Ssklower if (ns_nullhost(nsp->nsp_faddr)) {
44921479Ssklower error = ENOTCONN;
45021479Ssklower break;
45121479Ssklower }
45221479Ssklower }
45321479Ssklower error = idp_output(nsp, m);
45421479Ssklower m = NULL;
45521479Ssklower if (nam) {
45621479Ssklower ns_pcbdisconnect(nsp);
45721479Ssklower splx(s);
45821479Ssklower nsp->nsp_laddr.x_host = laddr.x_host;
45921479Ssklower nsp->nsp_laddr.x_port = laddr.x_port;
46021479Ssklower }
46121479Ssklower }
46221479Ssklower break;
46321479Ssklower
46421479Ssklower case PRU_ABORT:
46521479Ssklower ns_pcbdetach(nsp);
46621479Ssklower sofree(so);
46721479Ssklower soisdisconnected(so);
46821479Ssklower break;
46921479Ssklower
47021479Ssklower case PRU_SOCKADDR:
47121479Ssklower ns_setsockaddr(nsp, nam);
47221479Ssklower break;
47321479Ssklower
47421479Ssklower case PRU_PEERADDR:
47521479Ssklower ns_setpeeraddr(nsp, nam);
47621479Ssklower break;
47721479Ssklower
47821479Ssklower case PRU_SENSE:
47921479Ssklower /*
48021479Ssklower * stat: don't bother with a blocksize.
48121479Ssklower */
48221479Ssklower return (0);
48321479Ssklower
48421479Ssklower case PRU_SENDOOB:
48521479Ssklower case PRU_FASTTIMO:
48621479Ssklower case PRU_SLOWTIMO:
48721479Ssklower case PRU_PROTORCV:
48821479Ssklower case PRU_PROTOSEND:
48921479Ssklower error = EOPNOTSUPP;
49021479Ssklower break;
49121479Ssklower
49221479Ssklower case PRU_CONTROL:
49321479Ssklower case PRU_RCVD:
49421479Ssklower case PRU_RCVOOB:
49521479Ssklower return (EOPNOTSUPP); /* do not free mbuf's */
49621479Ssklower
49721479Ssklower default:
49821479Ssklower panic("idp_usrreq");
49921479Ssklower }
50021479Ssklower release:
50141921Ssklower if (control != NULL)
50241921Ssklower m_freem(control);
50321479Ssklower if (m != NULL)
50421479Ssklower m_freem(m);
50521479Ssklower return (error);
50621479Ssklower }
50721479Ssklower /*ARGSUSED*/
50841921Ssklower idp_raw_usrreq(so, req, m, nam, control)
50921479Ssklower struct socket *so;
51021479Ssklower int req;
51141921Ssklower struct mbuf *m, *nam, *control;
51221479Ssklower {
51321479Ssklower int error = 0;
51421479Ssklower struct nspcb *nsp = sotonspcb(so);
51521479Ssklower extern struct nspcb nsrawpcb;
51621479Ssklower
51721479Ssklower switch (req) {
51821479Ssklower
51921479Ssklower case PRU_ATTACH:
52021479Ssklower
52150238Ssklower if (!(so->so_state & SS_PRIV) || (nsp != NULL)) {
52221479Ssklower error = EINVAL;
52321479Ssklower break;
52421479Ssklower }
52521479Ssklower error = ns_pcballoc(so, &nsrawpcb);
52621479Ssklower if (error)
52721479Ssklower break;
52834500Skarels error = soreserve(so, (u_long) 2048, (u_long) 2048);
52921479Ssklower if (error)
53021479Ssklower break;
53121479Ssklower nsp = sotonspcb(so);
53221479Ssklower nsp->nsp_faddr.x_host = ns_broadhost;
53321479Ssklower nsp->nsp_flags = NSP_RAWIN | NSP_RAWOUT;
53421479Ssklower break;
53521479Ssklower default:
53641921Ssklower error = idp_usrreq(so, req, m, nam, control);
53721479Ssklower }
53823500Ssklower return (error);
53921479Ssklower }
54021479Ssklower
541