1 /*
2 * Copyright (c) 1988 University of Utah.
3 * Copyright (c) 1990, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * the Systems Programming Group of the University of Utah Computer
8 * Science Department.
9 *
10 * %sccs.include.redist.c%
11 *
12 * from: Utah $Hdr: hpux_net.c 1.8 93/08/02$
13 *
14 * @(#)hpux_net.c 8.3 (Berkeley) 02/19/95
15 */
16
17 /*
18 * Network related HP-UX compatibility routines
19 */
20
21 #ifdef HPUXCOMPAT
22
23 #include <sys/param.h>
24 #include <sys/systm.h>
25 #include <sys/kernel.h>
26 #include <sys/time.h>
27 #include <sys/errno.h>
28 #include <sys/proc.h>
29 #include <sys/file.h>
30 #include <sys/mbuf.h>
31 #include <sys/socket.h>
32 #include <sys/socketvar.h>
33 #include <sys/uio.h>
34 #include <sys/ktrace.h>
35
36 #include <hp/hpux/hpux.h>
37
38 #define MINBSDIPCCODE 0x3EE
39 #define NUMBSDIPC 32
40
41 /*
42 * HPUX netioctl() to BSD syscall map.
43 * Indexed by callno - MINBSDIPCCODE
44 */
45 extern int socket(), listen(), bind(), compat_43_accept(), connect();
46 extern int compat_43_recv(), compat_43_send(), shutdown();
47 extern int compat_43_getsockname(), sendto(), compat_43_recvfrom();
48 extern int compat_43_getpeername();
49 int hpuxgetsockopt(), hpuxsetsockopt();
50
51 struct hpuxtobsdipc {
52 int (*rout)();
53 int nargs;
54 } hpuxtobsdipc[NUMBSDIPC] = {
55 socket, 3, /* 3ee */ listen, 2, /* 3ef */
56 bind, 3, /* 3f0 */ compat_43_accept, 3, /* 3f1 */
57 connect, 3, /* 3f2 */ compat_43_recv, 4, /* 3f3 */
58 compat_43_send, 4, /* 3f4 */ shutdown, 2, /* 3f5 */
59 compat_43_getsockname, 3, /* 3f6 */ hpuxsetsockopt, 5, /* 3f7 */
60 sendto, 6, /* 3f8 */ compat_43_recvfrom, 6, /* 3f9 */
61 compat_43_getpeername, 3, /* 3fa */ NULL, 0, /* 3fb */
62 NULL, 0, /* 3fc */ NULL, 0, /* 3fd */
63 NULL, 0, /* 3fe */ NULL, 0, /* 3ff */
64 NULL, 0, /* 400 */ NULL, 0, /* 401 */
65 NULL, 0, /* 402 */ NULL, 0, /* 403 */
66 NULL, 0, /* 404 */ NULL, 0, /* 405 */
67 NULL, 0, /* 406 */ NULL, 0, /* 407 */
68 NULL, 0, /* 408 */ NULL, 0, /* 409 */
69 NULL, 0, /* 40a */ hpuxgetsockopt, 5, /* 40b */
70 NULL, 0, /* 40c */ NULL, 0, /* 40d */
71 };
72
73 /*
74 * Single system call entry to BSD style IPC.
75 * Gleened from disassembled libbsdipc.a syscall entries.
76 */
77 struct hpuxnetioctl_args {
78 int call;
79 int *args;
80 };
81 hpuxnetioctl(p, uap, retval)
82 struct proc *p;
83 struct hpuxnetioctl_args *uap;
84 int *retval;
85 {
86 int *args, i;
87 register int code;
88 int error;
89
90 args = uap->args;
91 code = uap->call - MINBSDIPCCODE;
92 if (code < 0 || code >= NUMBSDIPC || hpuxtobsdipc[code].rout == NULL)
93 return (EINVAL);
94 if ((i = hpuxtobsdipc[code].nargs * sizeof (int)) &&
95 (error = copyin((caddr_t)args, (caddr_t)uap, (u_int)i))) {
96 #ifdef KTRACE
97 if (KTRPOINT(p, KTR_SYSCALL))
98 ktrsyscall(p->p_tracep, code + MINBSDIPCCODE,
99 hpuxtobsdipc[code].nargs, (int *)uap);
100 #endif
101 return (error);
102 }
103 #ifdef KTRACE
104 if (KTRPOINT(p, KTR_SYSCALL))
105 ktrsyscall(p->p_tracep, code + MINBSDIPCCODE,
106 hpuxtobsdipc[code].nargs, (int *)uap);
107 #endif
108 return ((*hpuxtobsdipc[code].rout)(p, uap, retval));
109 }
110
socksetsize(size,m)111 socksetsize(size, m)
112 int size;
113 struct mbuf *m;
114 {
115 register int tmp;
116
117 if (size < sizeof(int)) {
118 switch(size) {
119 case 1:
120 tmp = (int) *mtod(m, char *);
121 break;
122 case 2:
123 tmp = (int) *mtod(m, short *);
124 break;
125 case 3:
126 tmp = (((int) *mtod(m, int *)) >> 8) & 0xffffff;
127 break;
128 }
129 *mtod(m, int *) = tmp;
130 m->m_len = sizeof(int);
131 } else {
132 m->m_len = size;
133 }
134 }
135
136 struct hpuxsetsockopt_args {
137 int s;
138 int level;
139 int name;
140 caddr_t val;
141 int valsize;
142 };
143 /* ARGSUSED */
144 hpuxsetsockopt(p, uap, retval)
145 struct proc *p;
146 struct hpuxsetsockopt_args *uap;
147 int *retval;
148 {
149 struct file *fp;
150 struct mbuf *m = NULL;
151 int tmp, error;
152
153 if (error = getsock(p->p_fd, uap->s, &fp))
154 return (error);
155 if (uap->valsize > MLEN)
156 return (EINVAL);
157 if (uap->val) {
158 m = m_get(M_WAIT, MT_SOOPTS);
159 if (m == NULL)
160 return (ENOBUFS);
161 if (error = copyin(uap->val, mtod(m, caddr_t),
162 (u_int)uap->valsize)) {
163 (void) m_free(m);
164 return (error);
165 }
166 if (uap->name == SO_LINGER) {
167 tmp = *mtod(m, int *);
168 mtod(m, struct linger *)->l_onoff = 1;
169 mtod(m, struct linger *)->l_linger = tmp;
170 m->m_len = sizeof(struct linger);
171 } else
172 socksetsize(uap->valsize, m);
173 } else if (uap->name == ~SO_LINGER) {
174 m = m_get(M_WAIT, MT_SOOPTS);
175 if (m) {
176 uap->name = SO_LINGER;
177 mtod(m, struct linger *)->l_onoff = 0;
178 m->m_len = sizeof(struct linger);
179 }
180 }
181 return (sosetopt((struct socket *)fp->f_data, uap->level,
182 uap->name, m));
183 }
184
185 struct hpuxsetsockopt2_args {
186 int s;
187 int level;
188 int name;
189 caddr_t val;
190 int valsize;
191 };
192 /* ARGSUSED */
193 hpuxsetsockopt2(p, uap, retval)
194 struct proc *p;
195 register struct hpuxsetsockopt2_args *uap;
196 int *retval;
197 {
198 struct file *fp;
199 struct mbuf *m = NULL;
200 int error;
201
202 if (error = getsock(p->p_fd, uap->s, &fp))
203 return (error);
204 if (uap->valsize > MLEN)
205 return (EINVAL);
206 if (uap->val) {
207 m = m_get(M_WAIT, MT_SOOPTS);
208 if (m == NULL)
209 return (ENOBUFS);
210 if (error = copyin(uap->val, mtod(m, caddr_t),
211 (u_int)uap->valsize)) {
212 (void) m_free(m);
213 return (error);
214 }
215 socksetsize(uap->valsize, m);
216 }
217 return (sosetopt((struct socket *)fp->f_data, uap->level,
218 uap->name, m));
219 }
220
221 struct hpuxgetsockopt_args {
222 int s;
223 int level;
224 int name;
225 caddr_t val;
226 int *avalsize;
227 };
228 hpuxgetsockopt(p, uap, retval)
229 struct proc *p;
230 struct hpuxgetsockopt_args *uap;
231 int *retval;
232 {
233 struct file *fp;
234 struct mbuf *m = NULL;
235 int valsize, error;
236
237 if (error = getsock(p->p_fd, uap->s, &fp))
238 return (error);
239 if (uap->val) {
240 if (error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize,
241 sizeof (valsize)))
242 return (error);
243 } else
244 valsize = 0;
245 if (error = sogetopt((struct socket *)fp->f_data, uap->level,
246 uap->name, &m))
247 goto bad;
248 if (uap->val && valsize && m != NULL) {
249 if (uap->name == SO_LINGER) {
250 if (mtod(m, struct linger *)->l_onoff)
251 *mtod(m, int *) = mtod(m, struct linger *)->l_linger;
252 else
253 *mtod(m, int *) = 0;
254 m->m_len = sizeof(int);
255 }
256 if (valsize > m->m_len)
257 valsize = m->m_len;
258 error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize);
259 if (error == 0)
260 error = copyout((caddr_t)&valsize,
261 (caddr_t)uap->avalsize, sizeof (valsize));
262 }
263 bad:
264 if (m != NULL)
265 (void) m_free(m);
266 return (error);
267 }
268 #endif
269