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.6 92/12/26$ 13 * 14 * @(#)hpux_net.c 8.1 (Berkeley) 06/10/93 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(), oaccept(), connect(), orecv(); 46 extern int osend(), shutdown(), ogetsockname(), sendto(); 47 extern int orecvfrom(), ogetpeername(); 48 int hpuxgetsockopt(), hpuxsetsockopt(); 49 50 struct hpuxtobsdipc { 51 int (*rout)(); 52 int nargs; 53 } hpuxtobsdipc[NUMBSDIPC] = { 54 socket, 3, /* 3ee */ listen, 2, /* 3ef */ 55 bind, 3, /* 3f0 */ oaccept, 3, /* 3f1 */ 56 connect, 3, /* 3f2 */ orecv, 4, /* 3f3 */ 57 osend, 4, /* 3f4 */ shutdown, 2, /* 3f5 */ 58 ogetsockname, 3, /* 3f6 */ hpuxsetsockopt, 5, /* 3f7 */ 59 sendto, 6, /* 3f8 */ orecvfrom, 6, /* 3f9 */ 60 ogetpeername, 3, /* 3fa */ NULL, 0, /* 3fb */ 61 NULL, 0, /* 3fc */ NULL, 0, /* 3fd */ 62 NULL, 0, /* 3fe */ NULL, 0, /* 3ff */ 63 NULL, 0, /* 400 */ NULL, 0, /* 401 */ 64 NULL, 0, /* 402 */ NULL, 0, /* 403 */ 65 NULL, 0, /* 404 */ NULL, 0, /* 405 */ 66 NULL, 0, /* 406 */ NULL, 0, /* 407 */ 67 NULL, 0, /* 408 */ NULL, 0, /* 409 */ 68 NULL, 0, /* 40a */ hpuxgetsockopt, 5, /* 40b */ 69 NULL, 0, /* 40c */ NULL, 0, /* 40d */ 70 }; 71 72 /* 73 * Single system call entry to BSD style IPC. 74 * Gleened from disassembled libbsdipc.a syscall entries. 75 */ 76 struct hpuxnetioctl_args { 77 int call; 78 int *args; 79 }; 80 hpuxnetioctl(p, uap, retval) 81 struct proc *p; 82 struct hpuxnetioctl_args *uap; 83 int *retval; 84 { 85 int *args, i; 86 register int code; 87 int error; 88 89 args = uap->args; 90 code = uap->call - MINBSDIPCCODE; 91 if (code < 0 || code >= NUMBSDIPC || hpuxtobsdipc[code].rout == NULL) 92 return (EINVAL); 93 if ((i = hpuxtobsdipc[code].nargs * sizeof (int)) && 94 (error = copyin((caddr_t)args, (caddr_t)uap, (u_int)i))) { 95 #ifdef KTRACE 96 if (KTRPOINT(p, KTR_SYSCALL)) 97 ktrsyscall(p->p_tracep, code + MINBSDIPCCODE, 98 hpuxtobsdipc[code].nargs); 99 #endif 100 return (error); 101 } 102 #ifdef KTRACE 103 if (KTRPOINT(p, KTR_SYSCALL)) 104 ktrsyscall(p->p_tracep, code + MINBSDIPCCODE, 105 hpuxtobsdipc[code].nargs); 106 #endif 107 return ((*hpuxtobsdipc[code].rout)(p, uap, retval)); 108 } 109 110 socksetsize(size, m) 111 int size; 112 struct mbuf *m; 113 { 114 register int tmp; 115 116 if (size < sizeof(int)) { 117 switch(size) { 118 case 1: 119 tmp = (int) *mtod(m, char *); 120 break; 121 case 2: 122 tmp = (int) *mtod(m, short *); 123 break; 124 case 3: 125 tmp = (((int) *mtod(m, int *)) >> 8) & 0xffffff; 126 break; 127 } 128 *mtod(m, int *) = tmp; 129 m->m_len = sizeof(int); 130 } else { 131 m->m_len = size; 132 } 133 } 134 135 struct hpuxsetsockopt_args { 136 int s; 137 int level; 138 int name; 139 caddr_t val; 140 int valsize; 141 }; 142 /* ARGSUSED */ 143 hpuxsetsockopt(p, uap, retval) 144 struct proc *p; 145 struct hpuxsetsockopt_args *uap; 146 int *retval; 147 { 148 struct file *fp; 149 struct mbuf *m = NULL; 150 int tmp, error; 151 152 if (error = getsock(p->p_fd, uap->s, &fp)) 153 return (error); 154 if (uap->valsize > MLEN) 155 return (EINVAL); 156 if (uap->val) { 157 m = m_get(M_WAIT, MT_SOOPTS); 158 if (m == NULL) 159 return (ENOBUFS); 160 if (error = copyin(uap->val, mtod(m, caddr_t), 161 (u_int)uap->valsize)) { 162 (void) m_free(m); 163 return (error); 164 } 165 if (uap->name == SO_LINGER) { 166 tmp = *mtod(m, int *); 167 mtod(m, struct linger *)->l_onoff = 1; 168 mtod(m, struct linger *)->l_linger = tmp; 169 m->m_len = sizeof(struct linger); 170 } else 171 socksetsize(uap->valsize, m); 172 } else if (uap->name == ~SO_LINGER) { 173 m = m_get(M_WAIT, MT_SOOPTS); 174 if (m) { 175 uap->name = SO_LINGER; 176 mtod(m, struct linger *)->l_onoff = 0; 177 m->m_len = sizeof(struct linger); 178 } 179 } 180 return (sosetopt((struct socket *)fp->f_data, uap->level, 181 uap->name, m)); 182 } 183 184 struct hpuxsetsockopt2_args { 185 int s; 186 int level; 187 int name; 188 caddr_t val; 189 int valsize; 190 }; 191 /* ARGSUSED */ 192 hpuxsetsockopt2(p, uap, retval) 193 struct proc *p; 194 register struct hpuxsetsockopt2_args *uap; 195 int *retval; 196 { 197 struct file *fp; 198 struct mbuf *m = NULL; 199 int error; 200 201 if (error = getsock(p->p_fd, uap->s, &fp)) 202 return (error); 203 if (uap->valsize > MLEN) 204 return (EINVAL); 205 if (uap->val) { 206 m = m_get(M_WAIT, MT_SOOPTS); 207 if (m == NULL) 208 return (ENOBUFS); 209 if (error = copyin(uap->val, mtod(m, caddr_t), 210 (u_int)uap->valsize)) { 211 (void) m_free(m); 212 return (error); 213 } 214 socksetsize(uap->valsize, m); 215 } 216 return (sosetopt((struct socket *)fp->f_data, uap->level, 217 uap->name, m)); 218 } 219 220 struct hpuxgetsockopt_args { 221 int s; 222 int level; 223 int name; 224 caddr_t val; 225 int *avalsize; 226 }; 227 hpuxgetsockopt(p, uap, retval) 228 struct proc *p; 229 struct hpuxgetsockopt_args *uap; 230 int *retval; 231 { 232 struct file *fp; 233 struct mbuf *m = NULL; 234 int valsize, error; 235 236 if (error = getsock(p->p_fd, uap->s, &fp)) 237 return (error); 238 if (uap->val) { 239 if (error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize, 240 sizeof (valsize))) 241 return (error); 242 } else 243 valsize = 0; 244 if (error = sogetopt((struct socket *)fp->f_data, uap->level, 245 uap->name, &m)) 246 goto bad; 247 if (uap->val && valsize && m != NULL) { 248 if (uap->name == SO_LINGER) { 249 if (mtod(m, struct linger *)->l_onoff) 250 *mtod(m, int *) = mtod(m, struct linger *)->l_linger; 251 else 252 *mtod(m, int *) = 0; 253 m->m_len = sizeof(int); 254 } 255 if (valsize > m->m_len) 256 valsize = m->m_len; 257 error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize); 258 if (error == 0) 259 error = copyout((caddr_t)&valsize, 260 (caddr_t)uap->avalsize, sizeof (valsize)); 261 } 262 bad: 263 if (m != NULL) 264 (void) m_free(m); 265 return (error); 266 } 267 #endif 268