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