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