1*25202Skarels /**************************************************************************/
2*25202Skarels /*                                                                        */
3*25202Skarels /*                    miscellaneous ip routines                           */
4*25202Skarels /*                                                                        */
5*25202Skarels /**************************************************************************/
6*25202Skarels 
7*25202Skarels 
8*25202Skarels #include "../h/param.h"
9*25202Skarels #include "../h/mbuf.h"
10*25202Skarels #include "../h/protosw.h"
11*25202Skarels #include "../h/socket.h"
12*25202Skarels #include "../h/socketvar.h"
13*25202Skarels #include "../h/errno.h"
14*25202Skarels 
15*25202Skarels #include "../net/if.h"
16*25202Skarels #include "../net/route.h"
17*25202Skarels #include "../net/af.h"
18*25202Skarels #include "../net/netisr.h"
19*25202Skarels 
20*25202Skarels #include "../vax/mtpr.h"
21*25202Skarels 
22*25202Skarels #include "../bbnnet/in.h"
23*25202Skarels #include "../bbnnet/in_var.h"
24*25202Skarels #include "../bbnnet/net.h"
25*25202Skarels #include "../bbnnet/in_pcb.h"
26*25202Skarels #include "../bbnnet/fsm.h"
27*25202Skarels #include "../bbnnet/ip.h"
28*25202Skarels #include "../bbnnet/icmp.h"
29*25202Skarels 
30*25202Skarels 
31*25202Skarels ip_ioctl (inp, command, data)
32*25202Skarels struct inpcb *inp;
33*25202Skarels int command;
34*25202Skarels caddr_t	data;
35*25202Skarels {
36*25202Skarels     /* no IP ioctls */
37*25202Skarels     return in_ioctl (command, data);
38*25202Skarels }
39*25202Skarels 
ip_ctloutput(req,so,level,optname,optval)40*25202Skarels ip_ctloutput(req, so, level, optname, optval)
41*25202Skarels int req;
42*25202Skarels struct socket *so;
43*25202Skarels int level, optname;
44*25202Skarels struct mbuf **optval;
45*25202Skarels {
46*25202Skarels     struct inpcb *inp;
47*25202Skarels 
48*25202Skarels     /*
49*25202Skarels      * O.K., with the berkeley method of using the protocol number for the level,
50*25202Skarels      * what magic cookie should we use to distinguish between IP and the interfaces?
51*25202Skarels      */
52*25202Skarels     inp = sotoinpcb(so);
53*25202Skarels 
54*25202Skarels     switch(req)
55*25202Skarels     {
56*25202Skarels 	case PRCO_GETOPT:
57*25202Skarels 	    return(ip_getopt(inp,optname,optval));
58*25202Skarels 
59*25202Skarels 	case PRCO_SETOPT:
60*25202Skarels 	    return(ip_setopt(inp,optname,optval));
61*25202Skarels 
62*25202Skarels 	default:
63*25202Skarels 	    panic("ip_ctloutput");
64*25202Skarels     }
65*25202Skarels     /*NOTREACHED*/
66*25202Skarels }
67*25202Skarels 
68*25202Skarels ip_setopt (inpcb, command, data)
69*25202Skarels struct inpcb	*inpcb;
70*25202Skarels struct mbuf	**data;
71*25202Skarels {
72*25202Skarels     register int error = 0;
73*25202Skarels     register struct mbuf *m = *data;
74*25202Skarels 
75*25202Skarels     switch (command)
76*25202Skarels     {
77*25202Skarels       case SO_IPROUTE:
78*25202Skarels 	/* this probably breaks!! */
79*25202Skarels 	if (m->m_len == 0)
80*25202Skarels 	{
81*25202Skarels 	    /* turns off use of options */
82*25202Skarels 	    inpcb->inp_optlen = 0;
83*25202Skarels 	    break;
84*25202Skarels 	}
85*25202Skarels 	if ((m->m_len < (2 * sizeof(struct in_addr))) ||
86*25202Skarels 	    (m->m_len > (MAX_IPOPTLEN - sizeof(struct in_addr))) ||
87*25202Skarels 	    (m->m_len % sizeof(struct in_addr)))
88*25202Skarels 	{
89*25202Skarels 	    error = EINVAL;
90*25202Skarels 	    break;
91*25202Skarels 	}
92*25202Skarels 	/*
93*25202Skarels 	 * O.K., user process specifies it as:
94*25202Skarels 	 *      ->A->B->C->D
95*25202Skarels 	 * D must be our final destination (but we can't
96*25202Skarels 	 * check that since we haven't connected yet).
97*25202Skarels 	 * Convert this into a form for ip_output.
98*25202Skarels 	 */
99*25202Skarels 	inpcb->inp_optlen = m->m_len;
100*25202Skarels 	bcopy (mtod(m, caddr_t), inpcb->inp_options, (unsigned)m->m_len);
101*25202Skarels 
102*25202Skarels 	/*
103*25202Skarels 	 * Following could be moved to ip_send(), but let's
104*25202Skarels 	 * do it once for efficiency even though user may
105*25202Skarels 	 * retrieve different from what stored.
106*25202Skarels 	 */
107*25202Skarels 	{
108*25202Skarels 	    char	*p;
109*25202Skarels 	    struct in_addr *ipa;
110*25202Skarels 
111*25202Skarels 	    p = inpcb->inp_options;
112*25202Skarels 	    ipa = (struct in_addr *) p;
113*25202Skarels 	    ipa[m->m_len / sizeof(struct in_addr)] = ipa[0];
114*25202Skarels 	    p[0] = IP_NOP_OPT;
115*25202Skarels 	    p[1] = IP_LRTE_OPT;
116*25202Skarels 	    p[2] = m->m_len -1;
117*25202Skarels 	    p[3] = 4; /* offset: counting one based */
118*25202Skarels 	}
119*25202Skarels 	/*
120*25202Skarels 	 * Now we have a correct IP source route recorded,
121*25202Skarels 	 * and the first hop comes after the source route.
122*25202Skarels 	 */
123*25202Skarels 	break;
124*25202Skarels       default:
125*25202Skarels 	error = EINVAL;
126*25202Skarels     }
127*25202Skarels 
128*25202Skarels     /* they can futz with m */
129*25202Skarels     if (*data)
130*25202Skarels 	m_freem(*data);
131*25202Skarels 
132*25202Skarels     return (error);
133*25202Skarels }
134*25202Skarels 
135*25202Skarels ip_getopt (inpcb, command, data)
136*25202Skarels struct inpcb	*inpcb;
137*25202Skarels struct mbuf	**data;
138*25202Skarels {
139*25202Skarels     register error = 0;
140*25202Skarels     register struct mbuf *m = NULL;
141*25202Skarels 
142*25202Skarels     *data = NULL;	/* o.k. (no data sent on getsockopt) */
143*25202Skarels 
144*25202Skarels     switch (command)
145*25202Skarels     {
146*25202Skarels       case SO_IPROUTE:
147*25202Skarels 	if (!inpcb->inp_optlen)
148*25202Skarels 	    break;
149*25202Skarels 
150*25202Skarels 	m = m_get(M_WAIT, MT_SOOPTS);
151*25202Skarels 
152*25202Skarels 	if (m == 0)
153*25202Skarels 	    return(ENOBUFS);
154*25202Skarels 
155*25202Skarels 	m->m_len = inpcb->inp_optlen;
156*25202Skarels 
157*25202Skarels 	bcopy (inpcb->inp_options, mtod(m, caddr_t), (unsigned)m->m_len);
158*25202Skarels 	break;
159*25202Skarels 
160*25202Skarels       default:
161*25202Skarels 	error = EINVAL;
162*25202Skarels     }
163*25202Skarels     *data = m;
164*25202Skarels     return (error);
165*25202Skarels }
166*25202Skarels 
167*25202Skarels u_char inetctlerrmap[PRC_NCMDS] =
168*25202Skarels {
169*25202Skarels     ENETUNREACH,	/* PRC_IFDOWN: connection oriented protocols use
170*25202Skarels 			 * interface with their local address.  Can't re-route.
171*25202Skarels 			 */
172*25202Skarels 
173*25202Skarels 	ECONNABORTED,	0,		0,
174*25202Skarels 	0,		0,		EHOSTDOWN,	EHOSTUNREACH,
175*25202Skarels 	ENETUNREACH,	EHOSTUNREACH,	ECONNREFUSED,	ECONNREFUSED,
176*25202Skarels 	EMSGSIZE,	0,		0,		0,
177*25202Skarels 	0,		0,		0,		0
178*25202Skarels } ;
179