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 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